Hello,
We want to get GemStone to talk to the Sybase libraries and then build a Seaside app in GemStone. We understand that FFI would be an easier route to follow than userActions would be and that FFI works in GS 3. How should we approach this?
What we did was to get maglev build 24566 running. Do we now bootstrap GLASS? Once GLASS is in, where do we get some info on how to use FFI? Cheers Otto
|
Otto,
I haven't played with FFI yet ... I'll find out what information we have and let you know.. Dale On 11/09/2010 05:46 AM, Otto Behrens wrote: > Hello, > > We want to get GemStone to talk to the Sybase libraries and then build a > Seaside app in GemStone. We understand that FFI would be an easier route > to follow than userActions would be and that FFI works in GS 3. How > should we approach this? > > What we did was to get maglev build 24566 running. Do we now bootstrap > GLASS? Once GLASS is in, where do we get some info on how to use FFI? > > Cheers > Otto |
In reply to this post by otto
Otto,
Here's the skinny. There are 6 classes involved in the FFI interface: CLibrary CFunction CCallIn CCallOut CByteArray CPointer The documentation is in comments on the class side. The attached .gs files are unit tests and testua.c is contains the c functions used by CFunction.gs. We're still pre-Beta so this is a great time for feedback ... send questions comments to this list and Allen will respond. There is C structure support on the ruby side (see the FFI module) and it is possible that we'll do something similar to Smalltalk (let us know how useful you think this support would be on the Smalltalk side). Dale On 11/09/2010 05:46 AM, Otto Behrens wrote: > Hello, > > We want to get GemStone to talk to the Sybase libraries and then build a > Seaside app in GemStone. We understand that FFI would be an easier route > to follow than userActions would be and that FFI works in GS 3. How > should we approach this? > > What we did was to get maglev build 24566 running. Do we now bootstrap > GLASS? Once GLASS is in, where do we get some info on how to use FFI? > > Cheers > Otto CFunction.gs (18K) Download Attachment CByteArray.gs (6K) Download Attachment testua.c (48K) Download Attachment |
Great; thanks Dale. We'll have a look today.
On Tue, Nov 9, 2010 at 9:06 PM, Dale Henrichs <[hidden email]> wrote: Otto, |
Hi,
The files start with a subclass of CoreTestCase. Is this something you wrote? Where can I get it? Cheers Otto |
We got a call through to a Sybase library! But it broke the topaz
session because we are not calling it correctly. This c function takes a reference to a pointer to a struct and then mallocs the struct and populates this struct with stuff. Where do I look for ideas or examples for this? Any ideas on how to do structs with this FFI? Here is an example C client for this library: context = (CS_CONTEXT *)NULL; ret = cs_ctx_alloc(EX_CTLIB_VERSION, &context); Thanks Otto On Wed, Nov 10, 2010 at 11:52 AM, Otto Behrens <[hidden email]> wrote: > Hi, > > The files start with a subclass of CoreTestCase. Is this something you > wrote? Where can I get it? > > Cheers > Otto > |
In reply to this post by otto
You should be able to just use TestCase to run the tests ...
CoreTestCase has some additional support methods that I don't think are used (although I'm not 100% sure:) Dale On 11/10/2010 01:52 AM, Otto Behrens wrote: > Hi, > > The files start with a subclass of CoreTestCase. Is this something you > wrote? Where can I get it? > > Cheers > Otto |
In reply to this post by otto
Excellent!
Here's some sample code for dealing with a struct: | addressOfContext referenceToContext | addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" "make the call to cs_ctx_alloc() with <addressOfContext> passed in as arg of type #ptr" referenceToContext := addressOfContext pointerAt: 0 resultClass: CByteArray. "<referenceToContext> is a CByteArray wrapping the ptr to the struct, so you can use instance methods of CByteArray to access the struct fields" Does this get you started? Dale On 11/10/2010 04:33 AM, Otto Behrens wrote: > We got a call through to a Sybase library! But it broke the topaz > session because we are not calling it correctly. This c function takes > a reference to a pointer to a struct and then mallocs the struct and > populates this struct with stuff. Where do I look for ideas or > examples for this? Any ideas on how to do structs with this FFI? > > Here is an example C client for this library: > context = (CS_CONTEXT *)NULL; > ret = cs_ctx_alloc(EX_CTLIB_VERSION,&context); > > Thanks > Otto > > On Wed, Nov 10, 2010 at 11:52 AM, Otto Behrens<[hidden email]> wrote: >> Hi, >> >> The files start with a subclass of CoreTestCase. Is this something you >> wrote? Where can I get it? >> >> Cheers >> Otto >> |
Getting a round tuit now... :-)
> Here's some sample code for dealing with a struct: > > | addressOfContext referenceToContext | > addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" This call fails with ERROR 2258, Primitive failed , selector #'_newFrom:offset:numBytes:gcFree:' receiver CByteArray . (RuntimeError) So I'm not getting much further. Ideas? I'll try to dig further... Thanks |
PS. running this
| VERSION: 3.0.0, Mon Nov 1 14:13:55 2010 | | BUILD: 64bit-24566 | from maglev install On Fri, Nov 19, 2010 at 2:38 PM, Otto Behrens <[hidden email]> wrote: > Getting a round tuit now... :-) > >> Here's some sample code for dealing with a struct: >> >> | addressOfContext referenceToContext | >> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" > > This call fails with > > ERROR 2258, Primitive failed , selector > #'_newFrom:offset:numBytes:gcFree:' receiver CByteArray . > (RuntimeError) > > So I'm not getting much further. Ideas? I'll try to dig further... > > Thanks > |
In reply to this post by otto
>> | addressOfContext referenceToContext |
>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" Used gcMalloc: which didn't fail. But the library (I think) failed with "Invalid context pointer". Making progress... |
Best attempt so far. We are successfully calling the library, and it
seems to be complaining about how we're calling it. Still trying to read CByteArray and friends' documentation and methods. Still a bit foreign to me... run | f context addressOfContext referenceToContext | library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. addressOfContext := CByteArray gcMalloc: 8. referenceToContext := addressOfContext pointerAt: 0 resultClass: CByteArray. f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 args: #(#int64 #ptr). f callWith: { 15501. referenceToContext } % The context allocation routine failed. The following problem caused the failure: Invalid context pointer. On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens <[hidden email]> wrote: >>> | addressOfContext referenceToContext | >>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" > > Used gcMalloc: which didn't fail. But the library (I think) failed > with "Invalid context pointer". Making progress... > |
Here's the declaration of the function in the header(s):
typedef void CS_VOID; #define CS_CONTEXT CS_VOID typedef struct _cscontext CS_CONTEXT; #define CS_PUBLIC __stdcall typedef int CS_RETCODE; #define PROTOTYPE(s) s extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( CS_INT version, CS_CONTEXT **outptr )); On Fri, Nov 19, 2010 at 6:07 PM, Otto Behrens <[hidden email]> wrote: > Best attempt so far. We are successfully calling the library, and it > seems to be complaining about how we're calling it. Still trying to > read CByteArray and friends' documentation and methods. Still a bit > foreign to me... > > run > | f context addressOfContext referenceToContext | > library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. > addressOfContext := CByteArray gcMalloc: 8. > referenceToContext := addressOfContext > pointerAt: 0 > resultClass: CByteArray. > f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 > args: #(#int64 #ptr). > f callWith: { 15501. referenceToContext } > % > > The context allocation routine failed. > > The following problem caused the failure: > > Invalid context pointer. > > > On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens <[hidden email]> wrote: >>>> | addressOfContext referenceToContext | >>>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" >> >> Used gcMalloc: which didn't fail. But the library (I think) failed >> with "Invalid context pointer". Making progress... >> > |
Otto,
I've forwarded your questions along and will let you know what I find out ... Dale On 11/19/2010 08:24 AM, Otto Behrens wrote: > Here's the declaration of the function in the header(s): > > typedef void CS_VOID; > #define CS_CONTEXT CS_VOID > typedef struct _cscontext CS_CONTEXT; > #define CS_PUBLIC __stdcall > typedef int CS_RETCODE; > #define PROTOTYPE(s) s > > extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( > CS_INT version, > CS_CONTEXT **outptr > )); > > > On Fri, Nov 19, 2010 at 6:07 PM, Otto Behrens<[hidden email]> wrote: >> Best attempt so far. We are successfully calling the library, and it >> seems to be complaining about how we're calling it. Still trying to >> read CByteArray and friends' documentation and methods. Still a bit >> foreign to me... >> >> run >> | f context addressOfContext referenceToContext | >> library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. >> addressOfContext := CByteArray gcMalloc: 8. >> referenceToContext := addressOfContext >> pointerAt: 0 >> resultClass: CByteArray. >> f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 >> args: #(#int64 #ptr). >> f callWith: { 15501. referenceToContext } >> % >> >> The context allocation routine failed. >> >> The following problem caused the failure: >> >> Invalid context pointer. >> >> >> On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens<[hidden email]> wrote: >>>>> | addressOfContext referenceToContext | >>>>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" >>> >>> Used gcMalloc: which didn't fail. But the library (I think) failed >>> with "Invalid context pointer". Making progress... >>> >> |
In reply to this post by otto
Otto,
I have attached Allen's response... Dale On 11/19/2010 08:24 AM, Otto Behrens wrote: > Here's the declaration of the function in the header(s): > > typedef void CS_VOID; > #define CS_CONTEXT CS_VOID > typedef struct _cscontext CS_CONTEXT; > #define CS_PUBLIC __stdcall > typedef int CS_RETCODE; > #define PROTOTYPE(s) s > > extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( > CS_INT version, > CS_CONTEXT **outptr > )); > > > On Fri, Nov 19, 2010 at 6:07 PM, Otto Behrens<[hidden email]> wrote: >> Best attempt so far. We are successfully calling the library, and it >> seems to be complaining about how we're calling it. Still trying to >> read CByteArray and friends' documentation and methods. Still a bit >> foreign to me... >> >> run >> | f context addressOfContext referenceToContext | >> library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. >> addressOfContext := CByteArray gcMalloc: 8. >> referenceToContext := addressOfContext >> pointerAt: 0 >> resultClass: CByteArray. >> f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 >> args: #(#int64 #ptr). >> f callWith: { 15501. referenceToContext } >> % >> >> The context allocation routine failed. >> >> The following problem caused the failure: >> >> Invalid context pointer. >> >> >> On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens<[hidden email]> wrote: >>>>> | addressOfContext referenceToContext | >>>>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" >>> >>> Used gcMalloc: which didn't fail. But the library (I think) failed >>> with "Invalid context pointer". Making progress... >>> >> On 11/19/2010 10:10 AM, Dale Henrichs wrote: > addressOfContext := CByteArray gcMalloc: 8. > referenceToContext := addressOfContext > pointerAt: 0 > resultClass: CByteArray. > f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 > args: #(#int64 #ptr). > f callWith: { 15501. referenceToContext } .... ============ From Otto's emails: typedef void CS_VOID; #define CS_CONTEXT CS_VOID typedef struct _cscontext CS_CONTEXT; #define CS_PUBLIC __stdcall typedef int CS_RETCODE; #define PROTOTYPE(s) s extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( CS_INT version, CS_CONTEXT **outptr )); ---- run | f context addressOfContext referenceToContext | library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. addressOfContext := CByteArray gcMalloc: 8. referenceToContext := addressOfContext pointerAt: 0 resultClass: CByteArray. f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 args: #(#int64 #ptr). f callWith: { 15501. referenceToContext } % ============ Allen's comments as you noted, malloc:8 is broken ; gcMalloc:8 is the workaround. I have opened Ticket 821 at magtrac.gemstone.com for this, it should be fixed in the next maglev release. Actually gcMalloc: is recommended if the lifetime of the C memory will be the same as the lifetime of the instance of CByteArray ; then the VM will automatically call free() when the CByteArray is garbage collected. If the underlyng library will ultimately call free() then you would have to use malloc: once Trac 821 is fixed. I'm assumming that in C you would be doing CS_CONTEXT *p = NULL; int aVersionNum = ??? ; CS_RETCODE status = cs_ctx_alloc(aVersionNum , &p); // now *p is memory allocated by cs_ctx_alloc. Notes for edited code below , a) use #ptr for second arg to args: . b) You should determine whether CS_INT is a C int or a C long . If it is NOT a long or an intptr_t , then it is 32 bits and you should declare the CCallout with args: #( #int32 #ptr ) . This should not matter on x86_64 but the implementation does try to cast accurately and on some CPUs the #int32 vs #int64 can make a difference in register usage . c) callWith: gets addressOfContext as second arg . The C code will see the address of the 8 bytes allocated in the gcMalloc:8 | f context addressOfContext referenceToContext | library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. f := CCallout library: library name: 'cs_ctx_alloc' result: #int args: #(#int64 #ptr). addressOfContext := CByteArray gcMalloc: 8. f callWith: { 15501. addressOfContext } . referenceToContext := addressOfContext pointerAt: 0 resultClass: CByteArray. "now referenceToContext is a CByteArray of indefinite size . you can use other instance methods of CByteArray to fetch/store from fields within the memory allocated by cs_ctx_alloc() " |
Hello,
Thanks for all the help. We've spent some time on this in drips and drabs and we made good progress. We are able to call the library and we got to the point where we could do "use <db name>" successfully. We also registered callbacks and the server fired the callback, which is great. We're not interpreting the result from a query yet, nor the error message in a callback. We need some examples to help with accessing members of structs; in some cases we need to pass a pointer to a struct to a function, which we struggle to figure out. Here is something I'm battling with: How to create pointers to objects and how to dereference pointers. For example: We (think we) understand that addressOfContext := CByteArray gcMalloc: 8 Creates an object which is allocated in the library's memory space. In the answer we got from you (which does work), we pass addressOfContext directly to the function: f callWith: { 15501. addressOfContext } My question is this: how can this work because the c call looks like this: CS_CONTEXT *addressOfContext; cs_ctx_alloc(aVersionNum , &addressOfContext); which means that the address of the pointer is passed in. I'd expect the FFI to work like this: declare the args of f with #(#int64 #'&ptr') pointerToContext := CPointer newFrom: addressOfContext. f callWith: { 15501. pointerToContext } This does not work, and I don't get it. Can you please help why passing addressOfContext directly works with an arg declaration of #ptr? I've got more questions, more later... Thanks a lot Otto On Fri, Nov 19, 2010 at 9:06 PM, Dale Henrichs <[hidden email]> wrote: > Otto, > > I have attached Allen's response... > > Dale > > On 11/19/2010 08:24 AM, Otto Behrens wrote: >> >> Here's the declaration of the function in the header(s): >> >> typedef void CS_VOID; >> #define CS_CONTEXT CS_VOID >> typedef struct _cscontext CS_CONTEXT; >> #define CS_PUBLIC __stdcall >> typedef int CS_RETCODE; >> #define PROTOTYPE(s) s >> >> extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( >> CS_INT version, >> CS_CONTEXT **outptr >> )); >> >> >> On Fri, Nov 19, 2010 at 6:07 PM, Otto Behrens<[hidden email]> wrote: >>> >>> Best attempt so far. We are successfully calling the library, and it >>> seems to be complaining about how we're calling it. Still trying to >>> read CByteArray and friends' documentation and methods. Still a bit >>> foreign to me... >>> >>> run >>> | f context addressOfContext referenceToContext | >>> library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. >>> addressOfContext := CByteArray gcMalloc: 8. >>> referenceToContext := addressOfContext >>> pointerAt: 0 >>> resultClass: CByteArray. >>> f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 >>> args: #(#int64 #ptr). >>> f callWith: { 15501. referenceToContext } >>> % >>> >>> The context allocation routine failed. >>> >>> The following problem caused the failure: >>> >>> Invalid context pointer. >>> >>> >>> On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens<[hidden email]> wrote: >>>>>> >>>>>> | addressOfContext referenceToContext | >>>>>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" >>>> >>>> Used gcMalloc: which didn't fail. But the library (I think) failed >>>> with "Invalid context pointer". Making progress... >>>> >>> > |
Woops.
Just saw this email ... I've forwarded it to Allen. Dale On 11/24/2010 07:45 AM, Otto Behrens wrote: > Hello, > > Thanks for all the help. We've spent some time on this in drips and > drabs and we made good progress. We are able to call the library and > we got to the point where we could do "use<db name>" successfully. We > also registered callbacks and the server fired the callback, which is > great. We're not interpreting the result from a query yet, nor the > error message in a callback. We need some examples to help with > accessing members of structs; in some cases we need to pass a pointer > to a struct to a function, which we struggle to figure out. > > Here is something I'm battling with: How to create pointers to objects > and how to dereference pointers. > > For example: > We (think we) understand that > addressOfContext := CByteArray gcMalloc: 8 > Creates an object which is allocated in the library's memory space. In > the answer we got from you (which does work), we pass addressOfContext > directly to the function: > > f callWith: { 15501. addressOfContext } > > My question is this: how can this work because the c call looks like this: > > CS_CONTEXT *addressOfContext; > cs_ctx_alloc(aVersionNum ,&addressOfContext); > > which means that the address of the pointer is passed in. I'd expect > the FFI to work like this: > > declare the args of f with #(#int64 #'&ptr') > > pointerToContext := CPointer newFrom: addressOfContext. > f callWith: { 15501. pointerToContext } > > This does not work, and I don't get it. Can you please help why > passing addressOfContext directly works with an arg declaration of > #ptr? > > I've got more questions, more later... > > Thanks a lot > Otto > > On Fri, Nov 19, 2010 at 9:06 PM, Dale Henrichs<[hidden email]> wrote: >> Otto, >> >> I have attached Allen's response... >> >> Dale >> >> On 11/19/2010 08:24 AM, Otto Behrens wrote: >>> >>> Here's the declaration of the function in the header(s): >>> >>> typedef void CS_VOID; >>> #define CS_CONTEXT CS_VOID >>> typedef struct _cscontext CS_CONTEXT; >>> #define CS_PUBLIC __stdcall >>> typedef int CS_RETCODE; >>> #define PROTOTYPE(s) s >>> >>> extern CS_RETCODE CS_PUBLIC cs_ctx_alloc PROTOTYPE(( >>> CS_INT version, >>> CS_CONTEXT **outptr >>> )); >>> >>> >>> On Fri, Nov 19, 2010 at 6:07 PM, Otto Behrens<[hidden email]> wrote: >>>> >>>> Best attempt so far. We are successfully calling the library, and it >>>> seems to be complaining about how we're calling it. Still trying to >>>> read CByteArray and friends' documentation and methods. Still a bit >>>> foreign to me... >>>> >>>> run >>>> | f context addressOfContext referenceToContext | >>>> library := CLibrary named: '/opt/sybase15.5/OCS-15_0/lib/libsybct64.so'. >>>> addressOfContext := CByteArray gcMalloc: 8. >>>> referenceToContext := addressOfContext >>>> pointerAt: 0 >>>> resultClass: CByteArray. >>>> f := CCallout library: library name: 'cs_ctx_alloc' result: #int64 >>>> args: #(#int64 #ptr). >>>> f callWith: { 15501. referenceToContext } >>>> % >>>> >>>> The context allocation routine failed. >>>> >>>> The following problem caused the failure: >>>> >>>> Invalid context pointer. >>>> >>>> >>>> On Fri, Nov 19, 2010 at 2:57 PM, Otto Behrens<[hidden email]> wrote: >>>>>>> >>>>>>> | addressOfContext referenceToContext | >>>>>>> addressOfContext := (CByteArray malloc: 8). "allocate 8 bytes for ptr" >>>>> >>>>> Used gcMalloc: which didn't fail. But the library (I think) failed >>>>> with "Invalid context pointer". Making progress... >>>>> >>>> >> |
Free forum by Nabble | Edit this page |