Unified FFI: pointer of String as function parameter

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Unified FFI: pointer of String as function parameter

Julien Delplanque
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


Reply | Threaded
Open this post in threaded view
|

Re: Unified FFI: pointer of String as function parameter

EstebanLM
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
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Unified FFI: pointer of String as function parameter

Julien Delplanque
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

Reply | Threaded
Open this post in threaded view
|

Re: Unified FFI: pointer of String as function parameter

Julien Delplanque
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
>>
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: Unified FFI: pointer of String as function parameter

EstebanLM

> 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
>>>
>>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Unified FFI: pointer of String as function parameter

Julien Delplanque

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
>>>>
>>>>
>>
>