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.