FFI bug? (was Passing a char[] inside a struct to an FFI call)
C. David Shaffer
cdshaffer at acm.org
Sun Dec 12 01:54:13 UTC 2004
I should mention that I also tried
fields
"self defineFields"
^#((someNumber 'long') (someString 'byte' 255))
but it generated
someString: anObject
"This method was automatically generated"
handle unsignedByteAt: 5 put: anObject
which only copies a single byte into the struct. I tried various
combinations of char*, byte* as well. Looking at the code that I posted
I don't think that I need to jump through so many hoops with the strings
(my extension method is not needed) but I was just trying everything I
could think of. Is there a bug in the FFI field definition code which
ignores the field size parameter?
David
C. David Shaffer wrote:
> Hi folks,
>
> I'm stumped on an FFI issue. I want to allocate and send a:
>
> typedef struct {
> int someNumber;
> char someString[255];
> } MyStruct;
>
> into:
>
> int printIt(MyStruct* s, int size);
>
> So I declare an ExternalStructure subclass and specify fields on the
> class side as:
>
> fields
> "self defineFields"
> ^#((someNumber 'long') (someString 'ExternalData' 255))
>
> and
>
> apiPrintIt: me size: size
> <cdecl: long 'printIt' (SCExampleStruct* long) module: 'ffiexample'>
> ^self externalCallFailed
>
> but the generated mutator for someString doesn't copy all 255 bytes of
> my string. That is, it looks like:
>
> someString: anObject
> "This method was automatically generated"
> handle structAt: 5 put: anObject getHandle length: 4.
>
> My printIt method shows the first 4 bytes of the string but, as
> expected, doesn't get the rest right. I overrode class side byteSize
> to return 259 (255+4) but that didn't help. I hate to change this
> method since it was automatically generated and I don't understand the
> concequences of such a change. How should I really go about this?
>
> I have attached my code (for curious, helpful or insanely bored).
> Some hints would be helpful. I've read many of the e-mails on this
> list about FFI but I'm not making progress quickly enough. Here's my
> workspace:
>
> s _ SCExampleStruct new.
> s someNumber: 10.
> s someString: ('hhhhhhhhellllllo world' asExternalCString: 255).
> s printMe
>
> Lost and confused,
>
> David
>
>------------------------------------------------------------------------
>
>'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 10 December 2004 at 4:49:04 pm'!
>ExternalStructure subclass: #SCExampleStruct
> instanceVariableNames: ''
> classVariableNames: ''
> poolDictionaries: ''
> category: 'PalmPilot'!
>
>!SCExampleStruct methodsFor: 'accessing' stamp: 'cds 12/10/2004 16:37'!
>someNumber
> "This method was automatically generated"
> ^handle signedLongAt: 1! !
>
>!SCExampleStruct methodsFor: 'accessing' stamp: 'cds 12/10/2004 16:37'!
>someNumber: anObject
> "This method was automatically generated"
> handle signedLongAt: 1 put: anObject! !
>
>!SCExampleStruct methodsFor: 'accessing' stamp: 'cds 12/10/2004 16:37'!
>someString
> "This method was automatically generated"
> ^ExternalData fromHandle: (handle structAt: 5 length: 4)! !
>
>!SCExampleStruct methodsFor: 'accessing' stamp: 'cds 12/10/2004 16:37'!
>someString: anObject
> "This method was automatically generated"
> handle structAt: 5 put: anObject getHandle length: 4.! !
>
>
>!SCExampleStruct methodsFor: 'apicalls' stamp: 'cds 12/10/2004 12:27'!
>apiPrintIt: me size: size
> <cdecl: long 'printIt' (SCExampleStruct* long) module: 'ffiexample'>
> ^self externalCallFailed ! !
>
>
>!SCExampleStruct methodsFor: 'api' stamp: 'cds 12/10/2004 12:28'!
>printMe
> self apiPrintIt: self size: 255+4.! !
>
>"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
>
>SCExampleStruct class
> instanceVariableNames: ''!
>
>!SCExampleStruct class methodsFor: 'fields' stamp: 'cds 12/10/2004 16:37'!
>byteSize
> ^255+4! !
>
>!SCExampleStruct class methodsFor: 'fields' stamp: 'cds 12/10/2004 16:37'!
>fields
> "self defineFields"
> ^#((someNumber 'long') (someString 'ExternalData' 255))! !
>
>
>SCExampleStruct compileFields!
>
>
>------------------------------------------------------------------------
>
>#include "ffiexample.h"
>
>int printIt(MyStruct* s, int size) {
> int i;
> printf("%lx\n", s);
> printf("%d\n", size);
> printf("%d\n", s->someNumber);
> printf("%lx\n", s->someString);
> for(i=0; i < 255; i++) {
> printf("%hhx:", s->someString[i]);
> }
> printf("\n");
>}
>
>
>
>------------------------------------------------------------------------
>
>typedef struct {
> int someNumber;
> char someString[255];
>} MyStruct;
>
>
>------------------------------------------------------------------------
>
>'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 10 December 2004 at 4:51:12 pm'!
>
>!String methodsFor: '*PalmPilot' stamp: 'cds 12/10/2004 16:24'!
>asExternalCString: length
> | add |
> add := ExternalAddress allocate: length.
> self halt.
> 1 to: self size do: [:i |
> add byteAt: i put: (self at: i) asciiValue].
> add byteAt: self size + 1 put: 0.
> ^ExternalData fromHandle: add type: ExternalType char! !
>
>
>------------------------------------------------------------------------
>
>
>
>
More information about the Squeak-dev
mailing list
|