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 <[hidden email]> 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 :) Julien |
In reply to this post by EstebanLM
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 >>>> >>>> >> > |
Free forum by Nabble | Edit this page |