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 |
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 |
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 |
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 > |
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 >> |
Free forum by Nabble | Edit this page |