On 15 July 2015 at 11:16, Matthieu Lacaton <matthieu.laca...@gmail.com>
wrote:

> Hello Igor,
>
> Thanks for your answer.
>
> I implemented something like that for the printf function:
> Basically, it generates a method with matching arguments and executes it.
>
> *printf:* stringFormat *args:* tab
>>
>>     | argNumber functionArgs functionPrototype methodCorpse
>> methodSelector argsArray |
>>
>>     ((tab size % 2) = 0) ifFalse: [
>>         Transcript show: 'error'.
>>         ^self.
>>     ].
>>
>>     argNumber := 0.
>>     functionPrototype := 'printf: stringFormat'.
>>     functionArgs := ''.
>>     methodCorpse := ''.
>>     argsArray := (Array new: (tab size / 2) + 1).
>>     argsArray at: 1 put: stringFormat.
>>
>>     1 to: tab size by: 2 do: [ :i |
>>         functionPrototype := functionPrototype, ' arg', argNumber
>> asString, ': ', (tab at: i) asString, argNumber asString.
>>         functionArgs := functionArgs, ' ', (tab at: i) asString, ' ',
>> (tab at: i) asString, argNumber asString, ','.
>>         argsArray at: argNumber + 2 put: (tab at: i + 1).
>>         argNumber := argNumber + 1.
>>     ].
>>     functionArgs := functionArgs allButLast.
>>
>>     methodCorpse := functionPrototype, Character cr asString, '
>> <primitive: #primitiveNativeCall module: #NativeBoostPlugin>', Character cr
>> asString, Character cr asString, '    ^self nbCall: #( void printf ( String
>> stringFormat,', functionArgs asString, ' ) )', Character cr asString, '
>>     module: NativeBoost CLibrary'.
>>
>>     methodSelector := self class compile: methodCorpse.
>>
>>     self perform: methodSelector withArguments: argsArray.
>>
>
>
> Then you can call it like that :
>
> MyClass printf: 'Test of printf. String: %s, Int : %d, Long: %ld, Char:
> %c, Double: %lf' args: { 'String'. 'This is a string'. 'int'. 100. 'long'.
> 10000000. 'char'. 89. 'double'. 3.14159 }.
>
>
> I also tried it for some other variadic functions and, on my computer (I
> am running archlinux), it seemed to work for every type of argument except
> "float". It works fine for "double" though.
> For "char" you need to pass the integer ASCII value directly for it to
> work. I tried with "Character value: xxx" but it didn't work.
>
> I know that this is very hackish and very bad, and I am aware it has some
> drawbacks. Moreover I am not even sure it will work everytime.
> But for now it seems to work ...
>
> Oh man...
and why would anyone may want to use this? :)

Sure you can do whatever it takes to implement a feature you want so badly,
but hey..
If something that takes so much effort and so inefficient as result, would
you consider abandon the idea and use something else instead? :)
Because it is straightly against the philosophy of NB: be fast and explicit.
And you seem to be in favor of implicitness.
Well, nevertheless, it is a honorable goal, so good luck :)


> 2015-07-13 19:24 GMT+02:00 Igor Stasenko <siguc...@gmail.com>:
>
>>
>>
>> On 10 July 2015 at 10:18, Matthieu Lacaton <matthieu.laca...@gmail.com>
>> wrote:
>>
>>> Hello,
>>>
>>> Is it possible with NativeBoost to create a binding for a variadic
>>> function ?
>>>
>>> I've seen the printf example in NBCPrinter but this implementation is
>>> kind of cheating since it always pass just a %s as format and one already
>>> formatted string to the C function.
>>>
>>> I've written a simple variadic function which adds every integer it
>>> receives as argument (first argument is for the number of following
>>> arguments) :
>>>
>>> int add(int number,...);
>>>
>>> In Pharo I've tried something like this :
>>>
>>> *add: *number *arg1: *first *arg2: *second
>>>> <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
>>>>
>>>> ^ self nbCall: #( int add (int number, int first, int second))
>>>>   module: 'libMyLib.so'
>>>>
>>>
>>> and it works fine with two arguments.
>>>
>>> Basically, doing so, I would need one method per number of arguments so
>>> it's not very cool.
>>>
>>> I thought that maybe I could pass an array as argument to my Pharo
>>> method but I didn't really find a way to figure out how to define the
>>> nbCall without having a "Generic failure".
>>>
>>> *add: *number *args: *anArray
>>>> <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
>>>>
>>>> ^ self nbCall: #( int add (int number, ??? anArray))
>>>>   module: 'libMyLib.so'
>>>>
>>>
>>> Do you have an idea ?
>>>
>>>
>> In short, there's no marshaller for converting an array of items, to same
>> number of things on stack. That could solve the problem with your example:
>> passing array of objects of *same* type. But in general, it is not what C
>> variadic function(s) standing for. Because they stand for any number of
>> arguments, of any type.
>> In C, since all program is compiled statically, compiler knows the number
>> of passed arguments and their types through compiling each particular call
>> site(s) to variadic function. Which means that in fact, you are still
>> supplying all information needed by compiler *before* run time.
>>
>> In variadic functions, you can pass any arguments of any type,
>> but for converting each of them, you must tell NB what kind of
>> marshaller should be used for it , which means, that it is impossible to
>> know before run time, since you cannot know how many arguments you may
>> pass, not speaking about their types.
>>
>>
>>
>>
>>> Thanks,
>>>
>>> Matthieu
>>>
>>>
>>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>


-- 
Best regards,
Igor Stasenko.

Reply via email to