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 :)
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. 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? :)
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 <siguctua@gmail.com>:
On 15 July 2015 at 11:16, Matthieu Lacaton <matthieu.lacaton@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". 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 ...
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 :)
2015-07-13 19:24 GMT+02:00 Igor Stasenko <siguctua@gmail.com>:
On 10 July 2015 at 10:18, Matthieu Lacaton <matthieu.lacaton@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.