On 25 November 2012 23:11, Camillo Bruni <[email protected]> wrote:
> And don't forget to make the primitive declaration automatic, nobody can
> remember that cryptic string :)
>
once we'll have opal on board.. not before that. i don't want to hack
current compiler.

>
> On 2012-11-25, at 18:20, Igor Stasenko <[email protected]> wrote:
>
>> On 25 November 2012 21:59, Stéphane Ducasse <[email protected]> 
>> wrote:
>>> Igor your proposal looks nice.
>>>
>> it's not a proposal anymore..
>> i already made the changes :)
>>
>>> Stef
>>>
>>> On Nov 22, 2012, at 2:47 PM, Igor Stasenko wrote:
>>>
>>>> Hi,
>>>>
>>>> i am thinking about redesign of FFI top-level api, because it not very 
>>>> good.
>>>>
>>>> First thing is that NBFFICallout referenced in too many places (187 in
>>>> my image).
>>>> So, from one side, we should encourage using a convenience syntax, using
>>>>
>>>> self nbCall: ..
>>>> instead of
>>>> NBFFICallout ...
>>>>
>>>> but there's one more thing:
>>>> - a code generator has many different ways of use, and i actually
>>>> going to add another one,
>>>> but i see that it will explode the protocol(s) without make it
>>>> convenient to use.
>>>>
>>>> Imagine that you want to generate a callout to function, which address
>>>> cannot be obtained directly from external library.
>>>> This is actually a real issue, which Esteban met when implementing
>>>> bindings to Chipmunk library:
>>>> - some functions are not exposed directly by dynamic library, but 
>>>> indirectly:
>>>> the symbol(s) which library exports is not direct pointer(s) to
>>>> functions but instead
>>>> a pointers to variable, where the function pointer is stored.
>>>> So, in order to get function pointer , one needs first to get a
>>>> pointer to symbol, and then read the pointer value at that address.
>>>>
>>>> So, i thought that i would simply add new protocol to NBFFICallout:
>>>>
>>>> call: anonFunctionSignature convention: callConvention
>>>> functionAddress: aFunctionAddressBlock
>>>>
>>>> Then, one could use it like:
>>>>
>>>>      myMethod
>>>>              <primitive: #primitiveNativeCall module: #NativeBoostPlugin 
>>>> error: errorCode >
>>>>
>>>>              ^ NBFFICallout
>>>>                        call: #( int () )
>>>>                       convention: #cdecl functionAddress: [ self
>>>> getPointerTo: 'functionname' ]
>>>>
>>>> but it is too elaborate..
>>>> you can imagine that if one would like to implement a more convenient
>>>> form, he could just do:
>>>>
>>>>      myMethod
>>>>              <primitive: #primitiveNativeCall module: #NativeBoostPlugin 
>>>> error: errorCode >
>>>>
>>>>              ^ self indirectCall: #( int () ) name: 'functionname'
>>>>
>>>> or even:
>>>>
>>>>      myMethod
>>>>              <primitive: #primitiveNativeCall module: #NativeBoostPlugin 
>>>> error: errorCode >
>>>>
>>>>              ^ self indirectCall: #( int functionname () )
>>>>
>>>> now the problem is that you cannot wrap the NBFFICallout method in
>>>> order to implement convenience method, because of use of thisContext.
>>>>
>>>> I also concerned about exploding NBFFICallout public API.. which imo
>>>> doesn't makes much sense, because we should encourage the use of
>>>> convenience methods.
>>>>
>>>> So, i looking for improving public API:
>>>>
>>>> - First thing is getting rid of direct references to NBFFICallout..
>>>> - second thing is avoid tying public API with thisContext (so you can
>>>> create own convenience methods without much hassle).
>>>>
>>>> So, lets imagine what and how we can do it:
>>>>
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ NBFFICallout cdecl: #(  int foo() ) module: 'bar'
>>>>
>>>> 1. getting rid of global:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self nbCallout cdecl: #(  int foo() ) module: 'bar'
>>>>
>>>> 2. separating the call convention from signature:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self nbCallout cdecl call: #( int foo() ) module: 'bar'
>>>>
>>>> 3. as a bonus, since cdecl is most used, we can assume it is default:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self nbCallout call: #( int foo() ) module: 'bar'
>>>>
>>>> 4. avoid hardcoding module:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self nbCallout call: #( int foo() ) module: self module
>>>>
>>>> 5. pass code generation options as a separate message, instead of
>>>> additional keyword:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self nbCallout
>>>>            options: #( +optFoo - optBar);
>>>>            call: #( int foo() ) module: self module
>>>>
>>>> 6. finally users would want to do it in most convenient way:
>>>>
>>>> foo
>>>>      <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
>>>>
>>>>      ^ self call: #( int foo() )
>>>>
>>>> Which means that #call: is convenience method which they implement by
>>>> themselves.
>>>> Here how i think it should look like:
>>>>
>>>> call: fnSpec
>>>>
>>>>   ^ (self nbCalloutIn: thisContext sender)
>>>>      cdecl;
>>>>      options: #(+optFoo - optBar);
>>>>      call: fnSpec module: self module.
>>>>
>>>> If you look at current implementation of Object>>nbCall:
>>>>
>>>> nbCall: fnSpec
>>>>      " you can override this method if you need to"
>>>>
>>>>      | sender |
>>>>      sender := thisContext sender.
>>>>
>>>>      ^ NBFFICallout
>>>>              handleFailureIn: sender
>>>>              nativeCode: [ :gen |
>>>>                      gen
>>>>                              sender: sender;
>>>>                              callType: self nbCallingConvention;
>>>>                              generateCall: fnSpec module: self 
>>>> nbLibraryNameOrHandle]
>>>>
>>>> it is almost the same, except from cryptic use of blocks, and private
>>>> internal NBFFICallout methods which doing the job.
>>>>
>>>> So, basicly, i want to get rid of NBFFICallout class >>
>>>>  [cdecl/stdcall]: module: [options:]
>>>>  [cdecl/stdcall]: emitCall: [options:]
>>>>
>>>> and replace them with #call:module: and #call: emit:
>>>> and also add new one:
>>>> #call:address:
>>>>
>>>> which can be used for passing a function pointer directly.
>>>>
>>>> And any future extensions to public API will be a single method. Not
>>>> 2,3 or more, like today..
>>>>
>>>>
>>>> --
>>>> Best regards,
>>>> Igor Stasenko.
>>>>
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>



-- 
Best regards,
Igor Stasenko.

Reply via email to