Unified FFI: pointer of String as function parameter
Hello everyone, I have a C function to call from Pharo that looks like this: int my_function(char ** parameter); This function fill the pointer on the String given as parameter. How can I use this from pharo Unified FFI? I mean, how to get a pharo String filled by this function? Thanks in advance, Julien
this is not the easiest part of FFI :) this is the simplest way: str := ExternalAddress new. âThis will point to NULLâ self callToMyFunction: str. pharoString := (str pointerAt: 1) readString. callToMyFunction: str self ffiCall: #( void function ( char ** str ) ) now, another way is to declare a value holder: 1) subclass FFIExternalValueHolder. FFIExternalValueHolder subclass: #StringValueHolder. 2) implement class side method typeDesc StringValueHolder class>>typeDesc ^ String 3) implement your method replacing char** for your value holder: callToMyFunction: str self ffiCall: #( void function ( StringValueHolder* str ) ) then you call like this: str := StringValueHolder new. self callToMyFunction: str. pharoString := str value readString. looks like too much steps for just economise the âpointeAt: 1â part, but is useful when you have lots of this calls :) cheers, Esteban
On 30 May 2016, at 10:56, Julien Delplanque <julien@tamere.eu> wrote:
Hello everyone,
I have a C function to call from Pharo that looks like this:
int my_function(char ** parameter);
This function fill the pointer on the String given as parameter.
How can I use this from pharo Unified FFI? I mean, how to get a pharo String filled by this function?
Thanks in advance,
Julien
Thanks for the fast answer. :-) On 30/05/16 11:14, Esteban Lorenzano wrote:
this is not the easiest part of FFI :)
this is the simplest way:
str := ExternalAddress new. âThis will point to NULLâ self callToMyFunction: str. pharoString := (str pointerAt: 1) readString.
callToMyFunction: str self ffiCall: #( void function ( char ** str ) )
now, another way is to declare a value holder:
1) subclass FFIExternalValueHolder.
FFIExternalValueHolder subclass: #StringValueHolder.
2) implement class side method typeDesc
StringValueHolder class>>typeDesc ^ String
3) implement your method replacing char** for your value holder:
callToMyFunction: str self ffiCall: #( void function ( StringValueHolder* str ) )
then you call like this:
str := StringValueHolder new. self callToMyFunction: str. pharoString := str value readString.
looks like too much steps for just economise the âpointeAt: 1â part, but is useful when you have lots of this calls :) I think I will use the second solution. It is cleaner isn't it?
Julien
I just did it, it works directly except for 2 little mistakes (for people who are interested): The class method to override in StringValueHolder is #typeDecl and not #typeDesc. To get the actual String from the StringValueHolder, no need to call #readString on the result of #value, it causes an error because #value already returns a String. Thanks a lot for this explanation Esteban :-). Regards, Julien On 30/05/16 11:14, Esteban Lorenzano wrote:
this is not the easiest part of FFI :)
this is the simplest way:
str := ExternalAddress new. âThis will point to NULLâ self callToMyFunction: str. pharoString := (str pointerAt: 1) readString.
callToMyFunction: str self ffiCall: #( void function ( char ** str ) )
now, another way is to declare a value holder:
1) subclass FFIExternalValueHolder.
FFIExternalValueHolder subclass: #StringValueHolder.
2) implement class side method typeDesc
StringValueHolder class>>typeDesc ^ String
3) implement your method replacing char** for your value holder:
callToMyFunction: str self ffiCall: #( void function ( StringValueHolder* str ) )
then you call like this:
str := StringValueHolder new. self callToMyFunction: str. pharoString := str value readString.
looks like too much steps for just economise the âpointeAt: 1â part, but is useful when you have lots of this calls :)
cheers, Esteban
On 30 May 2016, at 10:56, Julien Delplanque <julien@tamere.eu> wrote:
Hello everyone,
I have a C function to call from Pharo that looks like this:
int my_function(char ** parameter);
This function fill the pointer on the String given as parameter.
How can I use this from pharo Unified FFI? I mean, how to get a pharo String filled by this function?
Thanks in advance,
Julien
On 30 May 2016, at 11:39, Julien Delplanque <julien@tamere.eu> wrote:
I just did it, it works directly except for 2 little mistakes (for people who are interested):
The class method to override in StringValueHolder is #typeDecl and not #typeDesc.
To get the actual String from the StringValueHolder, no need to call #readString on the result of #value, it causes an error because #value already returns a String.
oh well, I was coding by heart ;)
Thanks a lot for this explanation Esteban :-).
youâre welcome :) Esteban
Regards,
Julien
On 30/05/16 11:14, Esteban Lorenzano wrote:
this is not the easiest part of FFI :)
this is the simplest way:
str := ExternalAddress new. âThis will point to NULLâ self callToMyFunction: str. pharoString := (str pointerAt: 1) readString.
callToMyFunction: str self ffiCall: #( void function ( char ** str ) )
now, another way is to declare a value holder:
1) subclass FFIExternalValueHolder.
FFIExternalValueHolder subclass: #StringValueHolder.
2) implement class side method typeDesc
StringValueHolder class>>typeDesc ^ String
3) implement your method replacing char** for your value holder:
callToMyFunction: str self ffiCall: #( void function ( StringValueHolder* str ) )
then you call like this:
str := StringValueHolder new. self callToMyFunction: str. pharoString := str value readString.
looks like too much steps for just economise the âpointeAt: 1â part, but is useful when you have lots of this calls :)
cheers, Esteban
On 30 May 2016, at 10:56, Julien Delplanque <julien@tamere.eu> wrote:
Hello everyone,
I have a C function to call from Pharo that looks like this:
int my_function(char ** parameter);
This function fill the pointer on the String given as parameter.
How can I use this from pharo Unified FFI? I mean, how to get a pharo String filled by this function?
Thanks in advance,
Julien
On 30/05/16 11:44, Esteban Lorenzano wrote:
On 30 May 2016, at 11:39, Julien Delplanque <julien@tamere.eu> wrote:
I just did it, it works directly except for 2 little mistakes (for people who are interested):
The class method to override in StringValueHolder is #typeDecl and not #typeDesc.
To get the actual String from the StringValueHolder, no need to call #readString on the result of #value, it causes an error because #value already returns a String. oh well, I was coding by heart ;) Indeed, I mean no offense, I just wanted to fix this for people who will need to do this in the future. :-p
Thanks a lot for this explanation Esteban :-). youâre welcome :)
Esteban
Regards,
Julien
On 30/05/16 11:14, Esteban Lorenzano wrote:
this is not the easiest part of FFI :)
this is the simplest way:
str := ExternalAddress new. âThis will point to NULLâ self callToMyFunction: str. pharoString := (str pointerAt: 1) readString.
callToMyFunction: str self ffiCall: #( void function ( char ** str ) )
now, another way is to declare a value holder:
1) subclass FFIExternalValueHolder.
FFIExternalValueHolder subclass: #StringValueHolder.
2) implement class side method typeDesc
StringValueHolder class>>typeDesc ^ String
3) implement your method replacing char** for your value holder:
callToMyFunction: str self ffiCall: #( void function ( StringValueHolder* str ) )
then you call like this:
str := StringValueHolder new. self callToMyFunction: str. pharoString := str value readString.
looks like too much steps for just economise the âpointeAt: 1â part, but is useful when you have lots of this calls :)
cheers, Esteban
On 30 May 2016, at 10:56, Julien Delplanque <julien@tamere.eu> wrote:
Hello everyone,
I have a C function to call from Pharo that looks like this:
int my_function(char ** parameter);
This function fill the pointer on the String given as parameter.
How can I use this from pharo Unified FFI? I mean, how to get a pharo String filled by this function?
Thanks in advance,
Julien
participants (2)
-
Esteban Lorenzano -
Julien Delplanque