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? :)

[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.
> >>
> >>
> >>
> >>>
> >>> Thanks,
> >>>
> >>> Matthieu
> >>>
> >>>
> >>
> >>
> >>
> >> --
> >> Best regards,
> >> Igor Stasenko.
> >
> >
>
>


-- 
Best regards,
Igor Stasenko.

Reply via email to