On 28 August 2012 00:03, Walter Bright <newshound2@digitalmars.com> wrote:
On 8/27/2012 3:32 AM, Manu wrote:
Here's an advanced trick I use a lot since D doesn't extern to static C++
methods (heavily simplified, this is way out of context):

struct CPPClass
{
     this()
     {
         // not my actual code, but effectively, write 'this' and the C++ method
pointer into a delegate on initialisation [I wrap this process up using magic]
         void** pDelegate = cast(void**)&cppNonVirtualMethod;
         pDelegate[0] = this;
         pDelegate[1] = pCPPMethodPointer;
     }

     void delegate(int x = 0) cppNonVirtualMethod; // C++ methods often have
default args

       void delegate(int x) cppNonVirtualMethod;
       void callCppNonVirtualMethod(int x) { (*cppNonVirtualMethod)(x); }
       void callCppNonVirtualMethod() { callCppNonVirtualMethod(0); }

With inlining on, the calls to the second overload should disappear, and you have the same code generated as you would for the default arg method. You could probably reduce the typing with some sort of mixin template, but this is the basic idea.

I've actually considered this approach, and the overload isn't required in this case, since the true method can have a default arg. The same pattern can apply at the global scope.
There are 2 reasons I didn't go for it:

Every api call is a double-call with inlining turned off (debug builds). Debug builds are already slow enough, I didn't want to base a design decision on that when it was perfectly syntactically reasonable to call through the function pointers directly.
__forceinline would address this concern. (I really need this anyway for the simd api. simd intrinsics are all wrapped in templates; if these are not inlined, making a function call for every math opcode, it's gonna be waaaaay slower than using the fpu)

And the second is forward declarations and function definitiona appearing within the same file (I have a feature request on this).
The API is easily defined by the function pointer, but since the definition needs to define the default args, what now needs to be defined is a forward declaration/prototype.
The trouble is, my module magic mixin can't produce the bodies for the stubs it finds because a prototype and definition can't appear in the same file.

void functionDecl(int x = 10); // declaration by user (ideally with an custom attribute: @engine_import, which would inform the magic generating mixin to produce a stub and linkage code for this)

// **** magically generated by a mixin: ****
void function(int) __functionDecl_ptr;
__forceinline void functionDecl(int x)
{
   __functionDecl_ptr(x);
}
// **************
static this()
{
  __functionDecl_ptr = importExtern("functionDecl");
}
// **************

Sadly, there's a lot missing from the language to be able to do that, but I hope we can reach that place one day.