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
|