digitalmars.D.learn - extern (c++) std::function?
- Etienne Cimon (4/4) Aug 14 2014 I'm looking into making a binding for the C++ API called Botan, and the
- FreeSlave (9/13) Aug 15 2014 There are some restrictions about sharing complex types between
- =?ISO-8859-1?Q?R=E9my_Mou=EBza?= (75/84) Aug 15 2014 You'll certainly have to make a C++ wrapper. However, a delegate being
- Etienne (3/6) Aug 16 2014 Thanks for the detailed answer, this is the direction I'm going to be
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?
Aug 14 2014
On Friday, 15 August 2014 at 03:10:43 UTC, 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?There are some restrictions about sharing complex types between C++ and D. Currently only POD-structs and classes with virtual functions are supported for transparent interaction. In this case things become even more complicated since std::function is template class and D can't instantiate C++ templates. You should stick with some predefined signatures and make wrappers on C++ side, which will accept 'plane' functions and construct std::function.
Aug 15 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?
Aug 15 2014
On 2014-08-15 6:12 AM, R�my Mou�za wrote: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:Thanks for the detailed answer, this is the direction I'm going to be taking!
Aug 16 2014









"FreeSlave" <freeslave93 gmail.com> 