FFI bug? (was Passing a char[] inside a struct to an FFI call)

Andreas Raab andreas.raab at gmx.de
Sat Dec 11 06:57:26 UTC 2004


> Is there a bug in the FFI field definition code which ignores the field 
> size parameter?

The field size is exclusively used for padding, and no it isn't ignored. Try 
a spec like:

fields
    "self defineFields"
    ^#(
        (someNumber 'long')
        (someString 'byte' 255)
        (anotherLong 'long')
     )

and check the accessors for anotherLong.

Cheers,
  - Andreas

----- Original Message ----- 
From: "C. David Shaffer" <cdshaffer at acm.org>
To: "The general-purpose Squeak developers list" 
<squeak-dev at lists.squeakfoundation.org>
Sent: Saturday, December 11, 2004 5:54 PM
Subject: FFI bug? (was Passing a char[] inside a struct to an FFI call)


>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