www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Define "createXXX" functions for the constructors of class XXX

reply Johan Engelen <j j.nl> writes:
Hi all,
   While trying to interface C++ and D, I have to new a few D 
objects in C++ code. I am doing this using a D function: "XXX 
createXXX(...) { return new XXX(...); }".
I am sure there must be some great way to automatically generate 
these creator functions, but I don't know how to do it.

In the C++-header I will write manually:
   XXX* createXXX(int a, int b);
   XXX* createXXX(bool flag);

In D source:
   extern (C++) class XXX {
     this(int a, int b) { /+...+/ }
     this(bool flag) { /+...+/ }
   }

// Somehow define these guys automatically, 
"genCreateCtors!(XXX)" ?
   XXX createXXX(int a, int b) { return new XXX(a, b); }
   XXX createXXX(bool flag) { return new XXX(flag); }

Thanks a lot!
   Johan
Jan 23
next sibling parent tcak <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
On Saturday, 23 January 2016 at 19:42:29 UTC, Johan Engelen wrote:
 Hi all,
   While trying to interface C++ and D, I have to new a few D 
 objects in C++ code. I am doing this using a D function: "XXX 
 createXXX(...) { return new XXX(...); }".
 I am sure there must be some great way to automatically 
 generate these creator functions, but I don't know how to do it.

 In the C++-header I will write manually:
   XXX* createXXX(int a, int b);
   XXX* createXXX(bool flag);

 In D source:
   extern (C++) class XXX {
     this(int a, int b) { /+...+/ }
     this(bool flag) { /+...+/ }
   }

 // Somehow define these guys automatically, 
 "genCreateCtors!(XXX)" ?
   XXX createXXX(int a, int b) { return new XXX(a, b); }
   XXX createXXX(bool flag) { return new XXX(flag); }

 Thanks a lot!
   Johan
Wow! There are lots of XXX there. Anyway, I did a similar thing to yours for automatic attribute definition before. Three things: 1. Template 2. Mixin 3. Compile time function You define a compile time function which generates a string that is valid D code. You define template that takes some parameters (Your XXX values), and calls the function to merge them. In your class, you use mixin and template to generate the string and inject the generated code. Not that complex once you do it. Try to understand this code. http://david.rothlis.net/d/templates/ Its in there.
Jan 23
prev sibling next sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Sat, 23 Jan 2016 19:42:29 +0000, Johan Engelen wrote:
 // Somehow define these guys automatically, "genCreateCtors!(XXX)" ?
    XXX createXXX(int a, int b) { return new XXX(a, b); }
    XXX createXXX(bool flag) { return new XXX(flag); }
Check out http://dpaste.dzfl.pl/430dabf25935 I used string mixins to be absolutely, 100% sure that the right things ended up in the symbol table. __traits(getOverloads, Type, "name") gets function overloads for the given name. It gets them as an AliasSeq, which presents an array-like interface. Constructors use the name "__ctor". So you can get all constructors for a class named MyClass with: __traits(getOverloads, MyClass, "__ctor") This only includes explicitly defined constructors, not the default constructor, so we handle that separately. std.traits defines a Parameters template that takes a function and yields a parameter type tuple. We can hand it a constructor and it does the right thing. We can treat a bunch of values as one value if their type is a type tuple, so that's exactly what we do. Then it's just a bit of string manipulation to get the right class names and overloads in the right places and we've generated a string of D code that does what we want. Mix it in and Bob's your uncle. In your code, the line mixin(factory!MyClass); should be inside an extern(C++) block, naturally. The major caveat there: wherever you call "mixin(factory!MyClass);", you need MyClass to be in scope directly. If you have to refer to it with a qualified name, this will break. If that causes problems for you, you can use: extern(C++) { { import mypkg.mymodule : MyClass; mixin(factory!MyClass); } } And that should import just that class for just that one block of code.
Jan 23
parent Johan Engelen <j j.nl> writes:
Thanks for the rapid explanations and code!
Such a great forum :-)

Much obliged,
   Johan
Jan 24
prev sibling parent Johan Engelen <j j.nl> writes:
On Saturday, 23 January 2016 at 19:42:29 UTC, Johan Engelen wrote:
 Hi all,
   While trying to interface C++ and D, I have to new a few D 
 objects in C++ code. I am doing this using a D function: "XXX 
 createXXX(...) { return new XXX(...); }".
An easier way for trivial constructors (note parents!), is to also define the constructor inline in C++ header. in .d: extern (C++) class Klass { int b; this(int a) { b = a+1; } } in .h: class Klass { int b; Klass(int a) { b = a+1; } }; It's what DDMD does in a few cases.
Jan 24