Hi,

but this will not work either (I just realised). This is complicated matter and 
confuses many (even me, some times :P).
I will try explain. 

Technically, when you do 

array :=  (FFIExternalArray externalNewType: 'void*' size: parameters size) 
autoRelease.

you are declaring (in C)

(void*)[] array;

which (in C) is synonym of: 

void**

which means that as soon as you declare your array, you already have a void**

then, your call has to be: 

...
self prim_initEmbeddedRargc: parameters size argv: externalArray.

with call of: 

self ffiCall: #(int Rf_initEmbeddedR(int argc, FFIExternalArrayOfStrings argv))

(is better to declare a subclass of FFIExternalArray to be clear about your 
purpose). 

or the other way. Since UFFI cannot determine if an ExternalAddress is a 
pointer (void*) or a pointer to a pointer (void**), because for C, at the end, 
they are exactly the same, you need to declare as this: 

self prim_initEmbeddedRargc: parameters size argv: externalArray getHandle.

with call of: 

self ffiCall: #(int Rf_initEmbeddedR(int argc, void *argv))

remarks:
1) you need to declare it as “void*" because UFFI will box any arity > [object 
natural arity], which in arrays is 1 (then, if you pass ** it will box it into 
a –wrong– void***… bad.
2) in this case, since you are passing a handle (a pointer), you do not 
need/want to subclass FFIExternalArray.

Finally, a third way (not tested), is just doing: 

self prim_initEmbeddedRargc: parameters size argv: externalArray getHandle.

with call of: 

self ffiCall: #(int Rf_initEmbeddedR(int argc, oop argv))

in this case, it will pass the handle (pointer) “as is”, without 
transformation. This should work but I never tested it. 

Maybe in terms of clarity, last form is better… I don’t know :P

confusing? yes
but it is because is very hard to determine/parse/interpret pointer arities and 
keep the calls efficient, in a moment we need to put a limit in automatic 
translations.

Esteban

> On 04 Jun 2016, at 10:10, Esteban Lorenzano <esteba...@gmail.com> wrote:
> 
> Hi, 
> 
> sorry late response, I just missed this mails. 
> 
> but… I do not have much to say… what you did should work. 
> Except (I think I’d need to look at your code closer)  you need to change the 
> argument of argv to FFIExternalArray*, or you need to pass the handle to the 
> function. Something like this: 
> 
> 
> | externalArray parameters |
> 
> parameters  := #('R' '--no-save' 'silent').
> externalArray := (FFIExternalArray externalNewType: 'void*' size: parameters 
> size) autoRelease.
> parameters withIndexDo: [ :string :index | 
>       externalArray at: index put: (ExternalAddress fromString: string) 
> autoRelease ].
> self prim_initEmbeddedRargc: parameters size argv: externalArray getHandle
> 
> (with same primitive call)
> 
> or without the #getHandle message and a primitive call:
> 
> self ffiCall: #(int Rf_initEmbeddedR(int argc, FFIExternalArray* argv))
> 
> AFAIK, that should work… if not I’d need to take a better look, because is 
> maybe a bug :P
> 
> Esteban
> 
>> On 03 Jun 2016, at 18:50, Blondeau Vincent <vincent.blond...@worldline.com> 
>> wrote:
>> 
>> Hello,
>> 
>> So, we tried with Thibault Raffaillac and we succeed to have this kind of 
>> code:
>> 
>> 
>>       | externalArray |
>>       parameters  := #('R' '--no-save' 'silent').
>>       [ externalArray := FFIExternalArray externalNewType: 'void*' size: 
>> parameters size.
>>       parameters
>>               withIndexDo: [ :string :index | externalArray at: index put: 
>> (ExternalAddress fromString: string) ].
>>       self prim_initEmbeddedRargc: parameters size argv: externalArray ]
>>               ensure: [ externalArray
>>                               ifNotNil: [ externalArray do: [ :item | item 
>> ifNotNil: [ :e | e free ] ].
>>                                       externalArray free ] ]
>> 
>> with a primitive call:
>>       self ffiCall: #(int Rf_initEmbeddedR(int argc, char ** argv))
>> 
>> However, it still doesn't work because the VM is crashing during the call to 
>> the primitive.
>> 
>> Does the translation from the Nativeboost version is accurate?
>> 
>> Thanks in advance for your help,
>> 
>> Vincent
>> 
>>> -----Message d'origine-----
>>> De : Pharo-users [mailto:pharo-users-boun...@lists.pharo.org] De la part de
>>> Julien Delplanque
>>> Envoyé : mercredi 1 juin 2016 18:49
>>> À : pharo-users@lists.pharo.org
>>> Objet : Re: [Pharo-users] [UFFI] Call a function where argument type is 
>>> char **
>>> (argv)
>>> 
>>> Hello,
>>> 
>>> I asked a simililar question some days ago, maybe this [1] can help.
>>> 
>>> Regards,
>>> 
>>> Julien
>>> 
>>> Links:
>>> 
>>> [1]:
>>> http://forum.world.st/Unified-FFI-pointer-of-String-as-function-parameter-
>>> td4898066.html
>>> 
>>> 
>>> On 31/05/16 16:28, Blondeau Vincent wrote:
>>>> TL;DR: How to pass as argument an array of Strings (char **) with Unified-
>>> FFI?
>>>> 
>>>> Vincent
>>>> 
>>>> De : Blondeau Vincent
>>>> Envoyé : mercredi 25 mai 2016 13:58
>>>> À : Pharo Development List
>>>> Objet : [UFFI] Call a function where argument type is char ** (argv)
>>>> 
>>>> Hello,
>>>> 
>>>> I have written a R bridge in Pharo and I would like to migrate it from
>>> NativeBoost to UFFI.
>>>> Most of the changes are easy to do but I am stuck to a double pointer
>>> problem.
>>>> I have to call the function: int Rf_initEmbeddedR(int argc, char ** argv). 
>>>> I
>>> know how to give the int but the char ** is a problem. It is an array of 
>>> Strings.
>>>> 
>>>> With NB, I managed to have this (working) code:
>>>>                "This is 32bit... too bad..."
>>>>                strings := OrderedCollection new.
>>>>                par := NativeBoost allocate: 4 * params size.
>>>>                params
>>>>                                keysAndValuesDo: [ :i :each |
>>>>                                                | str |
>>>>                                                str := each 
>>>> asNBExternalString.
>>>>                                                strings add: str.
>>>>                                                par nbUInt32AtOffset: (i - 
>>>> 1) * 4 put: str value ].
>>>>                self prim_initEmbeddedRargc: params size argv: par ]
>>>>                                ensure: [
>>>>                                                "Free the memory we 
>>>> allocated"
>>>>                                                par ifNotNil: [ par free ].
>>>>                                                strings ifNotNil: [
>>>> strings do: [ :each | each free ] ] ]
>>>> 
>>>> With a primitive call:
>>>> Self nbCall: #(int Rf_initEmbeddedR(int argc, char *argv))
>>>> 
>>>> Do I still need to create my own array of strings or FFI creates it for me?
>>> How?
>>>> 
>>>> Thanks in advance for your answers,
>>>> 
>>>> Vincent
>>>> 
>>>> 
>>>> 
>>> !!!***************************************************************
>>> ****
>>>> ****************** "Ce message et les pièces jointes sont
>>>> confidentiels et réservés à l'usage exclusif de ses destinataires. Il peut
>>> également être protégé par le secret professionnel. Si vous recevez ce
>>> message par erreur, merci d'en avertir immédiatement l'expéditeur et de le
>>> détruire. L'intégrité du message ne pouvant être assurée sur Internet, la
>>> responsabilité de Worldline ne pourra être recherchée quant au contenu de
>>> ce message. Bien que les meilleurs efforts soient faits pour maintenir cette
>>> transmission exempte de tout virus, l'expéditeur ne donne aucune garantie à
>>> cet égard et sa responsabilité ne saurait être recherchée pour tout dommage
>>> résultant d'un virus transmis.
>>>> 
>>>> This e-mail and the documents attached are confidential and intended
>>> solely for the addressee; it may also be privileged. If you receive this 
>>> e-mail in
>>> error, please notify the sender immediately and destroy it. As its integrity
>>> cannot be secured on the Internet, the Worldline liability cannot be 
>>> triggered
>>> for the message content. Although the sender endeavours to maintain a
>>> computer virus-free network, the sender does not warrant that this
>>> transmission is virus-free and will not be liable for any damages resulting
>>> from any virus transmitted.!!!"
>>>> 
>>> 
>> 
>> 
>> !!!*************************************************************************************
>> "Ce message et les pièces jointes sont confidentiels et réservés à l'usage 
>> exclusif de ses destinataires. Il peut également être protégé par le secret 
>> professionnel. Si vous recevez ce message par erreur, merci d'en avertir 
>> immédiatement l'expéditeur et de le détruire. L'intégrité du message ne 
>> pouvant être assurée sur Internet, la responsabilité de Worldline ne pourra 
>> être recherchée quant au contenu de ce message. Bien que les meilleurs 
>> efforts soient faits pour maintenir cette transmission exempte de tout 
>> virus, l'expéditeur ne donne aucune garantie à cet égard et sa 
>> responsabilité ne saurait être recherchée pour tout dommage résultant d'un 
>> virus transmis.
>> 
>> This e-mail and the documents attached are confidential and intended solely 
>> for the addressee; it may also be privileged. If you receive this e-mail in 
>> error, please notify the sender immediately and destroy it. As its integrity 
>> cannot be secured on the Internet, the Worldline liability cannot be 
>> triggered for the message content. Although the sender endeavours to 
>> maintain a computer virus-free network, the sender does not warrant that 
>> this transmission is virus-free and will not be liable for any damages 
>> resulting from any virus transmitted.!!!"
>> 
> 


Reply via email to