It seems so simple...FFI help please?
Andrew Berg
andrew_c_berg at yahoo.com
Sat Sep 27 18:39:19 UTC 2003
I'm trying to call a library which returns all of its data through char
**'s. I'm pretty sure I could write a plugin to do this, but I would
prefer to use FFI. Here's an example of two basic functions with
signatures similar to this library:
--------------------------------------------------------------------------
int s_dup(char * in, char ** out);
int s_free(char * in);
--------------------------------------------------------------------------
These particular ones are just test functions I wrote in a test library:
--------------------------------------------------------------------------
int s_dup(char * in, char ** out)
{
printf("s_dup(%08x, %08x)", in, out);
if (out) printf(" ((%08x))", * out);
printf("\n");
* out = strdup(in);
return 0;
}
int s_free(char * in)
{
printf("s_free(%08x)", in);
if (in)
free(in);
return 0;
}
--------------------------------------------------------------------------
In English, the returned string is passed as an out parameter, which must
be freed by the client using a supplied function. Well, that was almost
English. So, to call these functions I made a FFIStringTest class:
--------------------------------------------------------------------------
'From Squeak3.5 of ''11 April 2003'' [latest update: #5180] on 27 September
2003 at 11:00:13 am'!
ExternalLibrary subclass: #FFIStringTest
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'FFI-StringTest'!
!FFIStringTest methodsFor: 'as yet unclassified' stamp: 'acb 9/27/2003
10:47'!
dup: str to: aStrPtr
"Copy the string passed in to us."
<cdecl: long 's_dup' (char * FFIStringPtr *) module: 'strt'>
^ self externalCallFailed! !
!FFIStringTest methodsFor: 'as yet unclassified' stamp: 'acb 9/26/2003
21:40'!
free: aStrPtr
"Free the string passed in to us."
<cdecl: long 's_free' (FFIStringPtr) module: 'strt'>
^ self externalCallFailed! !
--------------------------------------------------------------------------
And, a FFIStringPtr class, since 'char **' is not a happy parameter type:
--------------------------------------------------------------------------
'From Squeak3.5 of ''11 April 2003'' [latest update: #5180] on 27 September
2003 at 11:03:53 am'!
ExternalStructure subclass: #FFIStringPtr
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'FFI-StringTest'!
!FFIStringPtr methodsFor: 'as yet unclassified' stamp: 'acb 9/27/2003
08:01'!
str
"Dereference the pointer and return the string."
"^ (self handle pointerAt: 1) "
^ ( ExternalData fromHandle: self handle type: ExternalType char )
fromCString! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
FFIStringPtr class
instanceVariableNames: ''!
!FFIStringPtr class methodsFor: 'as yet unclassified' stamp: 'acb 9/27/2003
08:00'!
fields
"FFIStringPtr defineFields"
"Define a structure which is just a string pointer."
^#(
(ptr 'char *')
)! !
FFIStringPtr compileFields!
--------------------------------------------------------------------------
So, it seems to me that I'm pretty close, yet not so close at all. When I
run this:
--------------------------------------------------------------------------
| f p |
f _ FFIStringTest new.
p _ FFIStringPtr new.
f dup: 'hi there' to: p.
f free: p.
--------------------------------------------------------------------------
I get some of my printf output to the console, followed by an enormous
stack dump:
--------------------------------------------------------------------------
s_dup(08155e58, 40cdc904) ((40b283d1))
Segmentation fault
1087228576 ProtoObject>become:
1087228392 MethodContext>doesNotUnderstand:
1087228300 MethodContext>doesNotUnderstand:
1087228208 Behavior>removeSelectorSimply:
1087197804 Compiler>evaluate:in:to:notifying:ifFail:
1087198172 [] in ParagraphEditor>evaluateSelection
.
. (and a _bunch_ of lines of stuff that looks like Morphic handling of an
alt-d)
.
--------------------------------------------------------------------------
About as much as I can really say is that it is not getting to the s_free
call. Can anyone tell me what I'm doing wrong, or perhaps suggest another
place to look for documentation/comments?
Thanks,
-andrew
--
andrew_c_berg at yahoo.com
More information about the Squeak-dev
mailing list
|