dereferencing pointers to structs in FFI

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

dereferencing pointers to structs in FFI

otto
Hello,

We are not finding the FFI straightforward to work with. Can you
please help us to get some context? On what interface / basis is this
FFI implementation built? Is there some place where we can see more
examples (or documentation) on using it?

Can you please help us to get a pointer to a struct dereferenced with
the FFI? We've got 2 cases:

1. We define a callback for the sybase CT library. Whenever the server
needs to raise an error or pass information, the callback is invoked.
Here is a C example:

ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
                          (CS_VOID *)servermsg_callback);

#define CS_MAX_MSG              (CS_INT)1024;

typedef struct _cs_servermsg
{
        CS_MSGNUM    msgnumber;
        CS_INT          state;
        CS_INT          severity;
        CS_CHAR      text[CS_MAX_MSG];
        CS_INT          textlen;
        CS_CHAR      svrname[CS_MAX_NAME];
        CS_INT          svrnlen;
        CS_CHAR      proc[CS_MAX_NAME];
        CS_INT          proclen;
        CS_INT          line;
        CS_INT          status;
        CS_BYTE         sqlstate[CS_SQLSTATE_SIZE];
        CS_INT          sqlstatelen;
} CS_SERVERMSG;

servermsg_callback(CS_CONTEXT *cp, CS_CONNECTION *chp, CS_SERVERMSG *msgp)
{
        printf("\t%s\n", msgp->text);
}

in Smalltalk, we tried this:

cb := CCallin name: 'ct_server_message' result: #int64 args: { #ptr.
#ptr. #ptr }.
f := CCallout library: library name: 'ct_callback' result: #int64
args: { #ptr. #int64. #int64. #int64. cb }.
f callWith: { referenceToContext. 0. CS_SET. CS_SERVERMSG_CB. [
:context :connection :msg | | messageText |
                dereferencedMessage := msg newFrom: 0 numBytes: 8.
                messageText := dereferencedMessage stringFromCharStarAt: 3 * 8.
                (resultCodes at: #CS_SUCCEED) ] }.

When we make subsequent calls to the library, the callback breaks and
the call to the library fails. Are we approaching the dereferencing
correctly?

2. When we get a result set back from a SQL call to the library, we
get an array of structs back. Here is a C example:

typedef struct _cs_datafmt
{
        CS_CHAR         name[CS_MAX_NAME];
        CS_INT          namelen;
        CS_INT          datatype;
        CS_INT          format;
        CS_INT          maxlength;
        CS_INT          scale;
        CS_INT          precision;
        CS_INT          status;
        CS_INT          count;
        CS_INT          usertype;
        CS_LOCALE       *locale;
} CS_DATAFMT;

CS_DATAFMT          column;
int   datalength;
int   indicator;

column.datatype = CS_CHAR_TYPE;
column.format = CS_FMT_NULLTERM;
column.maxlength = MAXSTRING;
column.count = 1;
column.locale = NULL;
ct_bind(cmd, 1, &column, name, &datalength, &indicator);

We tried this in Smalltalk:

CS_MAX_NAME := 255.
CS_DATAFMT_SIZE := CS_MAX_NAME + (10 * 8).
CS_INT_TYPE := 8.
CS_FMT_UNUSED := 16r0.
column := CByteArray gcMalloc: CS_DATAFMT_SIZE.
column int64At: CS_MAX_NAME + 8 put: CS_INT_TYPE.
column int64At: CS_MAX_NAME + (2 * 8) put: CS_FMT_UNUSED.
column int64At: CS_MAX_NAME + (3 * 8) put: 8.
column int64At: CS_MAX_NAME + (7 * 8) put: 1.
column int64At: CS_MAX_NAME + (9 * 8) put: 0.
datalength := CByteArray gcMalloc: 8.
indicator := CByteArray gcMalloc: 8.
f := CCallout library: library name: 'ct_bind' result: #int64 args:
#(#ptr #int64 #ptr #'const char*' #'&int64' #'&int64').
f callWith: { command. 1. column. ''. datalength. indicator }.

This does not work. Because the callbacks don't work either, we don't
know what's going wrong. Can you please help?

Thanks a lot
Otto
Reply | Threaded
Open this post in threaded view
|

Re: dereferencing pointers to structs in FFI

Dale Henrichs
Otto,

I've forwarded your mail to Allen...

Dale

On 11/29/2010 02:17 AM, Otto Behrens wrote:

> Hello,
>
> We are not finding the FFI straightforward to work with. Can you
> please help us to get some context? On what interface / basis is this
> FFI implementation built? Is there some place where we can see more
> examples (or documentation) on using it?
>
> Can you please help us to get a pointer to a struct dereferenced with
> the FFI? We've got 2 cases:
>
> 1. We define a callback for the sybase CT library. Whenever the server
> needs to raise an error or pass information, the callback is invoked.
> Here is a C example:
>
> ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
>                            (CS_VOID *)servermsg_callback);
>
> #define CS_MAX_MSG              (CS_INT)1024;
>
> typedef struct _cs_servermsg
> {
>          CS_MSGNUM    msgnumber;
>          CS_INT          state;
>          CS_INT          severity;
>          CS_CHAR      text[CS_MAX_MSG];
>          CS_INT          textlen;
>          CS_CHAR      svrname[CS_MAX_NAME];
>          CS_INT          svrnlen;
>          CS_CHAR      proc[CS_MAX_NAME];
>          CS_INT          proclen;
>          CS_INT          line;
>          CS_INT          status;
>          CS_BYTE         sqlstate[CS_SQLSTATE_SIZE];
>          CS_INT          sqlstatelen;
> } CS_SERVERMSG;
>
> servermsg_callback(CS_CONTEXT *cp, CS_CONNECTION *chp, CS_SERVERMSG *msgp)
> {
>          printf("\t%s\n", msgp->text);
> }
>
> in Smalltalk, we tried this:
>
> cb := CCallin name: 'ct_server_message' result: #int64 args: { #ptr.
> #ptr. #ptr }.
> f := CCallout library: library name: 'ct_callback' result: #int64
> args: { #ptr. #int64. #int64. #int64. cb }.
> f callWith: { referenceToContext. 0. CS_SET. CS_SERVERMSG_CB. [
> :context :connection :msg | | messageText |
>                  dereferencedMessage := msg newFrom: 0 numBytes: 8.
>                  messageText := dereferencedMessage stringFromCharStarAt: 3 * 8.
>                  (resultCodes at: #CS_SUCCEED) ] }.
>
> When we make subsequent calls to the library, the callback breaks and
> the call to the library fails. Are we approaching the dereferencing
> correctly?
>
> 2. When we get a result set back from a SQL call to the library, we
> get an array of structs back. Here is a C example:
>
> typedef struct _cs_datafmt
> {
>          CS_CHAR         name[CS_MAX_NAME];
>          CS_INT          namelen;
>          CS_INT          datatype;
>          CS_INT          format;
>          CS_INT          maxlength;
>          CS_INT          scale;
>          CS_INT          precision;
>          CS_INT          status;
>          CS_INT          count;
>          CS_INT          usertype;
>          CS_LOCALE       *locale;
> } CS_DATAFMT;
>
> CS_DATAFMT          column;
> int   datalength;
> int   indicator;
>
> column.datatype = CS_CHAR_TYPE;
> column.format = CS_FMT_NULLTERM;
> column.maxlength = MAXSTRING;
> column.count = 1;
> column.locale = NULL;
> ct_bind(cmd, 1,&column, name,&datalength,&indicator);
>
> We tried this in Smalltalk:
>
> CS_MAX_NAME := 255.
> CS_DATAFMT_SIZE := CS_MAX_NAME + (10 * 8).
> CS_INT_TYPE := 8.
> CS_FMT_UNUSED := 16r0.
> column := CByteArray gcMalloc: CS_DATAFMT_SIZE.
> column int64At: CS_MAX_NAME + 8 put: CS_INT_TYPE.
> column int64At: CS_MAX_NAME + (2 * 8) put: CS_FMT_UNUSED.
> column int64At: CS_MAX_NAME + (3 * 8) put: 8.
> column int64At: CS_MAX_NAME + (7 * 8) put: 1.
> column int64At: CS_MAX_NAME + (9 * 8) put: 0.
> datalength := CByteArray gcMalloc: 8.
> indicator := CByteArray gcMalloc: 8.
> f := CCallout library: library name: 'ct_bind' result: #int64 args:
> #(#ptr #int64 #ptr #'const char*' #'&int64' #'&int64').
> f callWith: { command. 1. column. ''. datalength. indicator }.
>
> This does not work. Because the callbacks don't work either, we don't
> know what's going wrong. Can you please help?
>
> Thanks a lot
> Otto
Reply | Threaded
Open this post in threaded view
|

Re: dereferencing pointers to structs in FFI

Dale Henrichs
In reply to this post by otto
Otto,

We haven't developed a whole lot of FFI examples for Smalltalk up to
this point. I've shared all of the Smalltalk-based test cases with you
already.

The interface has been designed to support the ruby FFI requirements and
as I mentioned in an earlier email there is a fair amount of ruby code
that is wrapped around the base FFI implementation that performs a lot
of the heavy lifting for dealing with structs. I think the code is in
the ruby FFI module....at this point in time coming at it from the ruby
side might be your best bet.

We have plans to look at providing more API support for FFI, but we
haven't made any decisions about the direction we might take.

Dale

On 11/29/2010 02:17 AM, Otto Behrens wrote:

> Hello,
>
> We are not finding the FFI straightforward to work with. Can you
> please help us to get some context? On what interface / basis is this
> FFI implementation built? Is there some place where we can see more
> examples (or documentation) on using it?
>
> Can you please help us to get a pointer to a struct dereferenced with
> the FFI? We've got 2 cases:
>
> 1. We define a callback for the sybase CT library. Whenever the server
> needs to raise an error or pass information, the callback is invoked.
> Here is a C example:
>
> ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
>                            (CS_VOID *)servermsg_callback);
>
> #define CS_MAX_MSG              (CS_INT)1024;
>
> typedef struct _cs_servermsg
> {
>          CS_MSGNUM    msgnumber;
>          CS_INT          state;
>          CS_INT          severity;
>          CS_CHAR      text[CS_MAX_MSG];
>          CS_INT          textlen;
>          CS_CHAR      svrname[CS_MAX_NAME];
>          CS_INT          svrnlen;
>          CS_CHAR      proc[CS_MAX_NAME];
>          CS_INT          proclen;
>          CS_INT          line;
>          CS_INT          status;
>          CS_BYTE         sqlstate[CS_SQLSTATE_SIZE];
>          CS_INT          sqlstatelen;
> } CS_SERVERMSG;
>
> servermsg_callback(CS_CONTEXT *cp, CS_CONNECTION *chp, CS_SERVERMSG *msgp)
> {
>          printf("\t%s\n", msgp->text);
> }
>
> in Smalltalk, we tried this:
>
> cb := CCallin name: 'ct_server_message' result: #int64 args: { #ptr.
> #ptr. #ptr }.
> f := CCallout library: library name: 'ct_callback' result: #int64
> args: { #ptr. #int64. #int64. #int64. cb }.
> f callWith: { referenceToContext. 0. CS_SET. CS_SERVERMSG_CB. [
> :context :connection :msg | | messageText |
>                  dereferencedMessage := msg newFrom: 0 numBytes: 8.
>                  messageText := dereferencedMessage stringFromCharStarAt: 3 * 8.
>                  (resultCodes at: #CS_SUCCEED) ] }.
>
> When we make subsequent calls to the library, the callback breaks and
> the call to the library fails. Are we approaching the dereferencing
> correctly?
>
> 2. When we get a result set back from a SQL call to the library, we
> get an array of structs back. Here is a C example:
>
> typedef struct _cs_datafmt
> {
>          CS_CHAR         name[CS_MAX_NAME];
>          CS_INT          namelen;
>          CS_INT          datatype;
>          CS_INT          format;
>          CS_INT          maxlength;
>          CS_INT          scale;
>          CS_INT          precision;
>          CS_INT          status;
>          CS_INT          count;
>          CS_INT          usertype;
>          CS_LOCALE       *locale;
> } CS_DATAFMT;
>
> CS_DATAFMT          column;
> int   datalength;
> int   indicator;
>
> column.datatype = CS_CHAR_TYPE;
> column.format = CS_FMT_NULLTERM;
> column.maxlength = MAXSTRING;
> column.count = 1;
> column.locale = NULL;
> ct_bind(cmd, 1,&column, name,&datalength,&indicator);
>
> We tried this in Smalltalk:
>
> CS_MAX_NAME := 255.
> CS_DATAFMT_SIZE := CS_MAX_NAME + (10 * 8).
> CS_INT_TYPE := 8.
> CS_FMT_UNUSED := 16r0.
> column := CByteArray gcMalloc: CS_DATAFMT_SIZE.
> column int64At: CS_MAX_NAME + 8 put: CS_INT_TYPE.
> column int64At: CS_MAX_NAME + (2 * 8) put: CS_FMT_UNUSED.
> column int64At: CS_MAX_NAME + (3 * 8) put: 8.
> column int64At: CS_MAX_NAME + (7 * 8) put: 1.
> column int64At: CS_MAX_NAME + (9 * 8) put: 0.
> datalength := CByteArray gcMalloc: 8.
> indicator := CByteArray gcMalloc: 8.
> f := CCallout library: library name: 'ct_bind' result: #int64 args:
> #(#ptr #int64 #ptr #'const char*' #'&int64' #'&int64').
> f callWith: { command. 1. column. ''. datalength. indicator }.
>
> This does not work. Because the callbacks don't work either, we don't
> know what's going wrong. Can you please help?
>
> Thanks a lot
> Otto

Reply | Threaded
Open this post in threaded view
|

Re: dereferencing pointers to structs in FFI

otto
In reply to this post by otto
Hi,

Just to let you know that we got a query with some results going
between GemStone (using FFI) and Sybase (using the OCS CT library).
Next steps are for us to do some more porting of a higher level layer
that uses this. Progress!

Thanks
Otto

On Mon, Nov 29, 2010 at 12:17 PM, Otto Behrens <[hidden email]> wrote:

> Hello,
>
> We are not finding the FFI straightforward to work with. Can you
> please help us to get some context? On what interface / basis is this
> FFI implementation built? Is there some place where we can see more
> examples (or documentation) on using it?
>
> Can you please help us to get a pointer to a struct dereferenced with
> the FFI? We've got 2 cases:
>
> 1. We define a callback for the sybase CT library. Whenever the server
> needs to raise an error or pass information, the callback is invoked.
> Here is a C example:
>
> ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
>                          (CS_VOID *)servermsg_callback);
>
> #define CS_MAX_MSG              (CS_INT)1024;
>
> typedef struct _cs_servermsg
> {
>        CS_MSGNUM    msgnumber;
>        CS_INT          state;
>        CS_INT          severity;
>        CS_CHAR      text[CS_MAX_MSG];
>        CS_INT          textlen;
>        CS_CHAR      svrname[CS_MAX_NAME];
>        CS_INT          svrnlen;
>        CS_CHAR      proc[CS_MAX_NAME];
>        CS_INT          proclen;
>        CS_INT          line;
>        CS_INT          status;
>        CS_BYTE         sqlstate[CS_SQLSTATE_SIZE];
>        CS_INT          sqlstatelen;
> } CS_SERVERMSG;
>
> servermsg_callback(CS_CONTEXT *cp, CS_CONNECTION *chp, CS_SERVERMSG *msgp)
> {
>        printf("\t%s\n", msgp->text);
> }
>
> in Smalltalk, we tried this:
>
> cb := CCallin name: 'ct_server_message' result: #int64 args: { #ptr.
> #ptr. #ptr }.
> f := CCallout library: library name: 'ct_callback' result: #int64
> args: { #ptr. #int64. #int64. #int64. cb }.
> f callWith: { referenceToContext. 0. CS_SET. CS_SERVERMSG_CB. [
> :context :connection :msg | | messageText |
>                dereferencedMessage := msg newFrom: 0 numBytes: 8.
>                messageText := dereferencedMessage stringFromCharStarAt: 3 * 8.
>                (resultCodes at: #CS_SUCCEED) ] }.
>
> When we make subsequent calls to the library, the callback breaks and
> the call to the library fails. Are we approaching the dereferencing
> correctly?
>
> 2. When we get a result set back from a SQL call to the library, we
> get an array of structs back. Here is a C example:
>
> typedef struct _cs_datafmt
> {
>        CS_CHAR         name[CS_MAX_NAME];
>        CS_INT          namelen;
>        CS_INT          datatype;
>        CS_INT          format;
>        CS_INT          maxlength;
>        CS_INT          scale;
>        CS_INT          precision;
>        CS_INT          status;
>        CS_INT          count;
>        CS_INT          usertype;
>        CS_LOCALE       *locale;
> } CS_DATAFMT;
>
> CS_DATAFMT          column;
> int   datalength;
> int   indicator;
>
> column.datatype = CS_CHAR_TYPE;
> column.format = CS_FMT_NULLTERM;
> column.maxlength = MAXSTRING;
> column.count = 1;
> column.locale = NULL;
> ct_bind(cmd, 1, &column, name, &datalength, &indicator);
>
> We tried this in Smalltalk:
>
> CS_MAX_NAME := 255.
> CS_DATAFMT_SIZE := CS_MAX_NAME + (10 * 8).
> CS_INT_TYPE := 8.
> CS_FMT_UNUSED := 16r0.
> column := CByteArray gcMalloc: CS_DATAFMT_SIZE.
> column int64At: CS_MAX_NAME + 8 put: CS_INT_TYPE.
> column int64At: CS_MAX_NAME + (2 * 8) put: CS_FMT_UNUSED.
> column int64At: CS_MAX_NAME + (3 * 8) put: 8.
> column int64At: CS_MAX_NAME + (7 * 8) put: 1.
> column int64At: CS_MAX_NAME + (9 * 8) put: 0.
> datalength := CByteArray gcMalloc: 8.
> indicator := CByteArray gcMalloc: 8.
> f := CCallout library: library name: 'ct_bind' result: #int64 args:
> #(#ptr #int64 #ptr #'const char*' #'&int64' #'&int64').
> f callWith: { command. 1. column. ''. datalength. indicator }.
>
> This does not work. Because the callbacks don't work either, we don't
> know what's going wrong. Can you please help?
>
> Thanks a lot
> Otto
>
Reply | Threaded
Open this post in threaded view
|

Re: dereferencing pointers to structs in FFI

Dale Henrichs
Great!

I'm glad that you have been making progress...

Dale

On 12/10/2010 07:50 AM, Otto Behrens wrote:

> Hi,
>
> Just to let you know that we got a query with some results going
> between GemStone (using FFI) and Sybase (using the OCS CT library).
> Next steps are for us to do some more porting of a higher level layer
> that uses this. Progress!
>
> Thanks
> Otto
>
> On Mon, Nov 29, 2010 at 12:17 PM, Otto Behrens<[hidden email]>  wrote:
>> Hello,
>>
>> We are not finding the FFI straightforward to work with. Can you
>> please help us to get some context? On what interface / basis is this
>> FFI implementation built? Is there some place where we can see more
>> examples (or documentation) on using it?
>>
>> Can you please help us to get a pointer to a struct dereferenced with
>> the FFI? We've got 2 cases:
>>
>> 1. We define a callback for the sybase CT library. Whenever the server
>> needs to raise an error or pass information, the callback is invoked.
>> Here is a C example:
>>
>> ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
>>                           (CS_VOID *)servermsg_callback);
>>
>> #define CS_MAX_MSG              (CS_INT)1024;
>>
>> typedef struct _cs_servermsg
>> {
>>         CS_MSGNUM    msgnumber;
>>         CS_INT          state;
>>         CS_INT          severity;
>>         CS_CHAR      text[CS_MAX_MSG];
>>         CS_INT          textlen;
>>         CS_CHAR      svrname[CS_MAX_NAME];
>>         CS_INT          svrnlen;
>>         CS_CHAR      proc[CS_MAX_NAME];
>>         CS_INT          proclen;
>>         CS_INT          line;
>>         CS_INT          status;
>>         CS_BYTE         sqlstate[CS_SQLSTATE_SIZE];
>>         CS_INT          sqlstatelen;
>> } CS_SERVERMSG;
>>
>> servermsg_callback(CS_CONTEXT *cp, CS_CONNECTION *chp, CS_SERVERMSG *msgp)
>> {
>>         printf("\t%s\n", msgp->text);
>> }
>>
>> in Smalltalk, we tried this:
>>
>> cb := CCallin name: 'ct_server_message' result: #int64 args: { #ptr.
>> #ptr. #ptr }.
>> f := CCallout library: library name: 'ct_callback' result: #int64
>> args: { #ptr. #int64. #int64. #int64. cb }.
>> f callWith: { referenceToContext. 0. CS_SET. CS_SERVERMSG_CB. [
>> :context :connection :msg | | messageText |
>>                 dereferencedMessage := msg newFrom: 0 numBytes: 8.
>>                 messageText := dereferencedMessage stringFromCharStarAt: 3 * 8.
>>                 (resultCodes at: #CS_SUCCEED) ] }.
>>
>> When we make subsequent calls to the library, the callback breaks and
>> the call to the library fails. Are we approaching the dereferencing
>> correctly?
>>
>> 2. When we get a result set back from a SQL call to the library, we
>> get an array of structs back. Here is a C example:
>>
>> typedef struct _cs_datafmt
>> {
>>         CS_CHAR         name[CS_MAX_NAME];
>>         CS_INT          namelen;
>>         CS_INT          datatype;
>>         CS_INT          format;
>>         CS_INT          maxlength;
>>         CS_INT          scale;
>>         CS_INT          precision;
>>         CS_INT          status;
>>         CS_INT          count;
>>         CS_INT          usertype;
>>         CS_LOCALE       *locale;
>> } CS_DATAFMT;
>>
>> CS_DATAFMT          column;
>> int   datalength;
>> int   indicator;
>>
>> column.datatype = CS_CHAR_TYPE;
>> column.format = CS_FMT_NULLTERM;
>> column.maxlength = MAXSTRING;
>> column.count = 1;
>> column.locale = NULL;
>> ct_bind(cmd, 1,&column, name,&datalength,&indicator);
>>
>> We tried this in Smalltalk:
>>
>> CS_MAX_NAME := 255.
>> CS_DATAFMT_SIZE := CS_MAX_NAME + (10 * 8).
>> CS_INT_TYPE := 8.
>> CS_FMT_UNUSED := 16r0.
>> column := CByteArray gcMalloc: CS_DATAFMT_SIZE.
>> column int64At: CS_MAX_NAME + 8 put: CS_INT_TYPE.
>> column int64At: CS_MAX_NAME + (2 * 8) put: CS_FMT_UNUSED.
>> column int64At: CS_MAX_NAME + (3 * 8) put: 8.
>> column int64At: CS_MAX_NAME + (7 * 8) put: 1.
>> column int64At: CS_MAX_NAME + (9 * 8) put: 0.
>> datalength := CByteArray gcMalloc: 8.
>> indicator := CByteArray gcMalloc: 8.
>> f := CCallout library: library name: 'ct_bind' result: #int64 args:
>> #(#ptr #int64 #ptr #'const char*' #'&int64' #'&int64').
>> f callWith: { command. 1. column. ''. datalength. indicator }.
>>
>> This does not work. Because the callbacks don't work either, we don't
>> know what's going wrong. Can you please help?
>>
>> Thanks a lot
>> Otto
>>