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