On Fri, Jul 17, 2015 at 12:23 AM, Igor Stasenko <siguc...@gmail.com> wrote:
>
>
> On 15 July 2015 at 16:35, Ben Coman <b...@openinworld.com> wrote:
>>
>> On Wed, Jul 15, 2015 at 5:16 PM, 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".
>>
>>
>> Maybe NativeBoost does not do implicit type conversions that a C
>> compiler would do?
>
>
> It does not.
> But that's not an issue. The philosophy behind NB was to require from user
> explicit information about what types to use and how.
> The main reason behind that, is that the more explicit and detailed
> information you got at compilation time (in case of NB - code generation) ,
> the more simple and efficient generated code will be.
> In general, you don't want to generate trains of machine code to handle
> 1000+ of cases for converting a single argument (and then repeat the same
> for next function argument). It makes things slow and inefficient, not
> speaking that generated code also takes memory space.
> I don't want to make code generation too smart, and this is why i trying to
> avoid any implicitness: because else it makes users wonder why something
> works and something don't and he have no idea, because of tons and tons of
> contradicting implicit rules hidden behind the scenes.
>
> And let me remind you that despite that NB implements FFI to speak with C,
> it is not obliged to implement features of C language itself. It lets you
> speak with C programs, but not lets you write programs like in C (see the
> difference? :)

I wasn't implying that implicit type conversion was a good thing that
needed implementing -- but just a bump if it hadn't needed attention
to it before when C did it automagically.
cheers -ben

>
>> [1] "Because C will promote floats to doubles for functions that take
>> variable arguments"
>>
>> More info search [2] for:
>> *  "implicit type conversion"
>> *  "guess wrongly when the program uses floating-point formats in
>> scanf() or printf()"
>>
>> [1]
>> http://stackoverflow.com/questions/210590/why-does-scanf-need-lf-for-doubles-when-printf-is-okay-with-just-f
>>
>> [2] http://www.electroons.com/8051/ebooks/expert%20C%20programming.pdf
>>
>> cheers -ben
>>
>>
>> > 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 ...
>> >
>> > 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.

Reply via email to