extern (c++) std::function?

Rémy Mouëza via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Aug 15 03:12:38 PDT 2014


You'll certainly have to make a C++ wrapper. However, a delegate being 
implemented as a struct containing a context pointer and a function, you 
can get some degree of interoperability between C++ and D
(BUT note that it is an undocumented implementation detail subject to 
change without notice -- althought it hasn't changed in many years):

/* =========================================================== */
/// ddg.d
import std.stdio;
import std.string;

/// A C++ function that will take a D delegate.
extern (C) void callDg (immutable(char)* delegate (int, int));

/// A dummy class.
class X {
     /// This method can be used as a delegate.
     extern (C)
     immutable(char)* callMe (int i, int j) {
         return "%d, %d".format (i, j).toStringz;
     }
}

void main () {
     auto x = new X;
     callDg (&x.callMe);
}

/* =========================================================== */
/// cpp_dg.cpp
#include <iostream>

using namespace std;

/// A D delegate representation in C++.
struct Dg {
     /// The context pointer.
     void * ctx;

     /// The function within the delegate: the first argument is the 
context pointer.
     const char *(*dg) (void * ctx, int i, int j);

     /// C++ sugar: calling a struct Dg as a function.
     const char * operator ()(int i, int j) {
         return dg (ctx, i, j);
     }
};

/// Extern C allows D compatibilty.
extern "C" {
     void callDg (Dg dg) {
         /// Call the extern (C) D delegate.
         cout << dg (42, 7) << endl;
     }
}
/* =========================================================== */
$ g++ -c cpp_dg.cpp
$ dmd ddg.d cpp_dg.o -L-lstdc++
$ ./ddg
42, 7
/* =========================================================== */

According to http://en.cppreference.com/w/cpp/utility/functional/function: "
 > Class template std::function is a general-purpose polymorphic
 > function wrapper. Instances of std::function can store, copy, and
 > invoke any Callable target -- functions, lambda expressions, bind
 > expressions, or other function objects, as well as pointers to member
 > functions and pointers to data members.
"

Thus the struct Dg in the example above should be compatible with the 
Botan constructors.

Also, extern (C) delegates are not that convenient in D, especially with 
assignments of anonymous/inline ones. You may want to add a layer of 
abstraction to the API you expose in D so that user D delegates are used 
from a second extern (C) delegate itself used by the C++ wrapper:

class BotanStuff {
     protected void delegate (string) ddg;
     protected BotanWrapper wrapr;

     this (void delegate (string) dg) {
         ddg   = dg;
         wrapr = new BotanWrapper (& this.cppDg);
     }

     extern (C) void cppDg (immutable(char)* cStr) {
         import std.conv;
         dg (cStr.to!string);
     }
}

If you are planning to use Swig for your binding, this kind of wrapping 
may be conveniently done using custom typemaps.


On 08/15/2014 05:10 AM, Etienne Cimon wrote:
> I'm looking into making a binding for the C++ API called Botan, and the
> constructors in it take a std::function. I'm wondering if there's a D
> equivalent for this binding to work out, or if I have to make a C++
> wrapper as well?



More information about the Digitalmars-d-learn mailing list