Difference between revisions of "Calypso/TipsAndTricks"

From D Wiki
Jump to: navigation, search
(cppNew and cppDelete)
 
 
(5 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Constructing C++ classes or structs on malloc'd memory ==
+
== Constructing C++ classes or structs inside malloc'd memory ==
  
When a C++ library expects to be granted ownership on a piece of memory, the allocation shouldn't be done by the GC unless you keep a reference to the allocated memory at all times, which is pointless additional work and not always possible.
+
When a C++ library expects to be granted ownership of a piece of memory, the allocation shouldn't be done by the GC unless you always keep a reference to the allocated memory, which is pointless additional work and not always possible.
  
Calypso provides a small runtime library which contains some common utility functions, such as <code>cppNew</code> and <code>cppDelete</code> to bypass the GC while constructing C++ class/struct objects:
+
Calypso provides a small runtime library which contains some commonplace utility functions, such as <code>cppNew</code> and <code>cppDelete</code> to bypass the GC while constructing C++ class/struct objects:
  
 
<syntaxhighlight lang="D">
 
<syntaxhighlight lang="D">
Line 9: Line 9:
 
import (C++) std.unique_ptr;
 
import (C++) std.unique_ptr;
  
auto testClass = cppNew!MyCppClass(); // malloc then ctor call
+
auto testClass = cppNew!MyCppClass(...); // malloc then ctor call
 
unique_ptr!MyCppClass owner;
 
unique_ptr!MyCppClass owner;
 
owner.reset(testClass);
 
owner.reset(testClass);
Line 15: Line 15:
 
// testClass will be free'd by the owner's dtor
 
// testClass will be free'd by the owner's dtor
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
== New traits ==
 +
 +
Calypso provides a few new traits (some of them were needed for the implementation of C++ member function pointers, most of which is in the small Calypso runtime library):
 +
 +
==== isCpp ====
 +
<syntaxhighlight lang="D">
 +
static assert (__traits(isCpp, MyCppClass) == true);
 +
</syntaxhighlight>
 +
 +
==== getBaseOffset ====
 +
<syntaxhighlight lang="Cpp">
 +
struct Base { int n; };
 +
struct Base2 { int o; };
 +
 +
class Derived : public Base, public Base2 {};
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="D">
 +
static assert (__traits(getBaseOffset, Derived, Base2) == int.sizeof);
 +
</syntaxhighlight>
 +
Works with C++ structs and classes, and D classes.
 +
 +
==== getCppVirtualIndex ====
 +
Returns the <strong>C++</strong> virtual table offset (in bytes) of the function, or -1 if it's not a C++ virtual function or a D function overriding one. Remember that an "hybrid" D class deriving from a C++ class usually has two or more virtual tables, the D one and a C++ one.
 +
 +
<syntaxhighlight lang="Cpp">
 +
class MyCppClass {
 +
    virtual int foo();
 +
};
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="D">
 +
class DplusCpp {
 +
    override int foo() { return 123; }
 +
}
 +
 +
void main() {
 +
    writeln(__traits(getCppVirtualIndex, DplusCpp.foo)); // should prints sizeof(void*)*2 according to the Itanium ABI
 +
}
 +
</syntaxhighlight>
 +
 +
This trait was added for the library-side implementation of Itanium member function pointers.
 +
 +
[[Category:Experimental compilers]]

Latest revision as of 05:01, 27 March 2018

Constructing C++ classes or structs inside malloc'd memory

When a C++ library expects to be granted ownership of a piece of memory, the allocation shouldn't be done by the GC unless you always keep a reference to the allocated memory, which is pointless additional work and not always possible.

Calypso provides a small runtime library which contains some commonplace utility functions, such as cppNew and cppDelete to bypass the GC while constructing C++ class/struct objects:

import cpp.memory; // cppNew and cppDelete
import (C++) std.unique_ptr;

auto testClass = cppNew!MyCppClass(...); // malloc then ctor call
unique_ptr!MyCppClass owner;
owner.reset(testClass);

// testClass will be free'd by the owner's dtor

New traits

Calypso provides a few new traits (some of them were needed for the implementation of C++ member function pointers, most of which is in the small Calypso runtime library):

isCpp

static assert (__traits(isCpp, MyCppClass) == true);

getBaseOffset

struct Base { int n; };
struct Base2 { int o; };

class Derived : public Base, public Base2 {};
static assert (__traits(getBaseOffset, Derived, Base2) == int.sizeof);

Works with C++ structs and classes, and D classes.

getCppVirtualIndex

Returns the C++ virtual table offset (in bytes) of the function, or -1 if it's not a C++ virtual function or a D function overriding one. Remember that an "hybrid" D class deriving from a C++ class usually has two or more virtual tables, the D one and a C++ one.

class MyCppClass {
    virtual int foo();
};
class DplusCpp {
    override int foo() { return 123; }
}

void main() {
    writeln(__traits(getCppVirtualIndex, DplusCpp.foo)); // should prints sizeof(void*)*2 according to the Itanium ABI
}

This trait was added for the library-side implementation of Itanium member function pointers.