Hi, Ciprian. Yes, the number of arguments limit is a problem (which occurs 1% of the time), but if it occurs, it beating you hard :) But NativeBoost allows you to use instance variable names in function signature, (the max number of inst vars is 255, which is more than enough i think ;) ), and what is most important (as you noted) it doesn't breaking encapsulation, since methods having full right for accessing receiver's instance variables in their class scope. So, for making a binding to function which takes too many arguments, what you can do is to create a class: Object subclass: #MyBigFunctionBinding instanceVariableNames: 'var1 var2 .... var100' .. And then implement a method for FFI callout in it: MyBigFunctionBinding>>callThatFatThing <primitive: > ^ self call: #( int function (int var1, int var2 , ....... var100 )) Another approach is to create an NBExternalStructure which will have same memory layout as arguments of function (so if you pass it by value, it will push exactly same number of values in right order on stack): NBExternalStructure subclass: #BloatedArgs .. BloatedFnArgs class>>fieldsDesc #( int arg1; int arg2; . ... int arg200; ) then you can just do: MyBigFunctionBinding>>callThatFatThing: args <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (BloatedFnArgs args )) So, as you can see from above, you can deal with this problem one way or another. And given that it is just 1% of all C functions (or even less), personally, i don't think that it is worth extending a signature syntax. On 21 October 2012 21:36, Ciprian Teodorov <ciprian.teodorov@gmail.com> wrote:
Hi guys,
Over the weekend I had a look at NativeBoost FFI and I have enjoyed it. I really like this idea of taming the beast from high-level languages. However I ran into some problems with the number of arguments one can pass to a smaltalk method (it turns out to be 15 at max)... That bad for FFI especially when you want to interface with legacy c code without touching the C-stuff (header, object files, etc).
In consequence I've hacked my way around this limitation by introduction of a new type of arguments that we can pass to callouts. I call these arguments "in object arguments". The idea isn't new and is very simple, instead of passing 20 arguments to your function just pass one an array with all the arguments you need. Where it turns interesting is that I think we can pass more than just an array we can pass real objects (think about ParameterObject) that hold in their instance variables the arguments we want.
lets say that we want to call a function " int function(int x, int y)", now with the NativeBoost wrapper we will get a call something like
function_x: x y: y <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (int x, int y))
the idea is to replace x: y: with only one argument
function: anArgument <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (int anArgument@1, int anArgument@2))
or even
function: aPoint <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (int aPoint@x, int aPoint@y))
Yes this last example breaks the encapsulation a little bit by acceding directly to the instance variable of aPoint... but... well
this is not going to work unless you specify the class to use (which contains such instance variables), which will make signatures even more uglier, something like: function: aPoint <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (int aPoint@Point:x, int aPoint@Point:y)) and that amount of mess beyond acceptance levels, to my taste :)
another example will be:
function_arg1: a arg2: b <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self call: #( int function (int a@1, int a@2, int b@3, int b@1, int a@6))
Well that's all that I did this weekend.
Attached to this mail you can find a file-out of these developments... they include: 1. the idea presented above 2. refactoring of NBFFICallout argument loader creation 3. a small "extension/fix" of the skipSpace method (in spec parser) to skip all separators not just spaces (think about a header definition with tabs)
Thanks , i will look at it.
Well that's it folks, enjoy Cheers -- Dr. Ciprian TEODOROV Ingénieur Développement CAO
tél : 06 08 54 73 48 mail : ciprian.teodorov@gmail.com www.teodorov.ro
-- Best regards, Igor Stasenko.