Hello, Is it possible with NativeBoost to create a binding for a variadic function ?add: number arg1: first arg2: second add: number args: anArray Do you have an idea ? Thanks, Matthieu |
On 10 July 2015 at 10:18, Matthieu Lacaton <[hidden email]> wrote:
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.
-- Best regards,
Igor Stasenko. |
Hello Igor, Thanks for your answer.printf: stringFormat args: tab 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 ... 2015-07-13 19:24 GMT+02:00 Igor Stasenko <[hidden email]>:
|
On Wed, Jul 15, 2015 at 5:16 PM, Matthieu Lacaton
<[hidden email]> 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 <[hidden email]>: >> >> >> >> On 10 July 2015 at 10:18, Matthieu Lacaton <[hidden email]> >> 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. > > |
On 15 July 2015 at 16:35, Ben Coman <[hidden email]> wrote:
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 -- Best regards,
Igor Stasenko. |
In reply to this post by Matthieu
On 15 July 2015 at 11:16, Matthieu Lacaton <[hidden email]> wrote:
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 :)
-- Best regards,
Igor Stasenko. |
You are right. Actually it was just a workaround to see if I could bypass some of the "limitations" but it is definitely too ugly and inefficient to be useful. The C code will be changed to fit Pharo and that will do the trick.
You are definitely right once again. I noticed today that lately I was writing more C-ish code in Pharo than Smalltalk-ish code... But I really like NativeBoost :( 2015-07-16 18:33 GMT+02:00 Igor Stasenko <[hidden email]>:
|
In reply to this post by Igor Stasenko
On Fri, Jul 17, 2015 at 12:23 AM, Igor Stasenko <[hidden email]> wrote:
> > > On 15 July 2015 at 16:35, Ben Coman <[hidden email]> wrote: >> >> On Wed, Jul 15, 2015 at 5:16 PM, Matthieu Lacaton >> <[hidden email]> 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 <[hidden email]>: >> >> >> >> >> >> >> >> On 10 July 2015 at 10:18, Matthieu Lacaton <[hidden email]> >> >> >> 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. |
Of course, Ben, i understand that you may miss some of the feature(s), you get used to when doing things in C. But then consider what is involved to implement such feature because it means determining argument types at run time (at compile time it is impossible as well as 'compile once when it is invoked for the first time' that NB does ) That means that no matter how well you try, the implementation will suck.. because it will be very slow comparing to one that uses fixed-type fixed-argument number. My philosophy , in general, for programming is avoid bloat and inefficiency at all costs. When some feature requires bloat and going to be very inefficient, i simply saying 'No'. Especially at infrastructural level, which NB belongs to. Because one thing that you (of me) as implementer knows what is fast & cool and what is slow & inefficient, but then users come and start using things in a way you would never think your stuff will be ever used.. and start spreading inefficiency in their project(s). And more that that, once they get used to it, then you would be never able to remove it because it is there and everyone using it and some even loving it :) Best regards,
Igor Stasenko. |
On Mon, Jul 27, 2015 at 9:56 PM, Igor Stasenko <[hidden email]> wrote:
> >>> >>> 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 > > > Of course, Ben, i understand that you may miss some of the feature(s), you > get used to when doing things in C. Sorry I wasn't clear so just to emphasise, I agree NB should not implement such a feature. I was trying to say just that it should be explicit** that implicit type conversions are not supported. A lot of programmers at various levels of experience not very aware of implicit type conversions will probably be bitten by the same error. So to avoid the bites, I guess we need to teach this bit of C when teaching NB. ** perhaps with an example demonstrating it, but I don't know what that might be. cheers -ben > But then consider what is involved to implement such feature because it > means determining argument types at run time (at compile time it is > impossible as well as 'compile once when it is invoked for the first time' > that NB does ) > That means that no matter how well you try, the implementation will suck.. > because it will be very slow comparing to one that uses fixed-type > fixed-argument number. > > My philosophy , in general, for programming is avoid bloat and inefficiency > at all costs. When some feature requires bloat and going to be very > inefficient, i simply saying 'No'. > Especially at infrastructural level, which NB belongs to. > Because one thing that you (of me) as implementer knows what is fast & cool > and what is slow & inefficient, but then users come and start using things > in a way you would never think your stuff will be ever used.. and start > spreading inefficiency in their project(s). And more that that, once they > get used to it, then you would be never able to remove it because it is > there and everyone using it and some even loving it :) > > > -- > Best regards, > Igor Stasenko. |
Free forum by Nabble | Edit this page |