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