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? [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. > >