Created
November 24, 2011 16:28
-
-
Save MartinNowak/1391734 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
#include "array.hpp" | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
// This is header only, so we just need to create an empty compile unit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ARRAY_H | |
#define ARRAY_H | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
#include "d_new.hpp" | |
#include <iostream> | |
#include <typeinfo> | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
class Array | |
{ | |
public: | |
Array() | |
: _length(100) | |
, _ptr(d_new<double>(_length)) | |
{ std::cout << "Foo::Foo()" << std::endl; } | |
// destructor is called when being finalized | |
~Array() | |
{ std::cout << "Foo::~Foo()" << std::endl;} | |
virtual void printInfo() | |
{ std::cout << "typeid: " << typeid(Array).name() << " this:" << this << std::endl; } | |
virtual size_t length() | |
{ return _length; } | |
virtual double* ptr() | |
{ return _ptr; } | |
size_t _length; | |
double* _ptr; | |
}; | |
//........................................................................................ | |
Array* createArray() | |
{ | |
return d_new<Array>(); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module d_new; | |
import core.memory, std.conv; | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
alias extern(C) void function(void* p) CFinalizer; | |
enum Coffset = 2 * size_t.sizeof; | |
final class Finalizer | |
{ | |
~this() | |
{ | |
const func = cast(CFinalizer)(cast(void**)this)[1]; | |
func(cast(void*)this + Coffset); | |
// clear the monitor slot | |
(cast(void**)this)[1] = null; | |
} | |
} | |
static assert(__traits(classInstanceSize, Finalizer) == Coffset); | |
//........................................................................................ | |
extern(C) void* _d_new(size_t size, CFinalizer cfinalizer) | |
{ | |
if (cfinalizer !is null) | |
{ | |
auto p = GC.malloc(size + Coffset, GC.BlkAttr.FINALIZE); | |
emplace!Finalizer(p[0 .. Coffset]); | |
// using the monitor slot saves size_t.sizeof bytes | |
(cast(void**)p)[1] = cfinalizer; | |
return p + Coffset; | |
} | |
else | |
// assume only plain types | |
return GC.malloc(size, GC.BlkAttr.NO_SCAN); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef D_NEW_H | |
#define D_NEW_H | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
#include <new> // placement new | |
#include <cstring> // size_t, memset | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
namespace | |
{ | |
template <bool b, typename T> | |
struct enable_if; | |
template <typename T> | |
struct enable_if<true, T> | |
{ | |
typedef T type; | |
}; | |
//........................................................................................ | |
template <typename T> | |
struct is_class | |
{ | |
struct A { char _[1]; }; | |
struct B { char _[2]; }; | |
template <class U> static A test(void(U::*)()); | |
template <class U> static B test(...); | |
static const bool value = sizeof(test<T>(NULL)) == sizeof(A); | |
}; | |
}; | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
typedef void (*CFinalizer)(void*); | |
extern "C" | |
{ | |
/* Will allocate size bytes from the garbage collector. If a | |
* finalizer is given, it will be called before the memory is | |
* reclaimed. If no finalizer is given the allocated memory is not | |
* scanned for nested references. | |
*/ | |
void* _d_new(size_t size, CFinalizer cfinalizer); | |
} | |
//........................................................................................ | |
// creates a new class | |
template <class T> | |
typename enable_if<is_class<T>::value, T*>::type d_new() | |
{ | |
// C++ doesn't allow to take the address of a destructor create | |
// this helper function to work around this. | |
struct Dtor | |
{ | |
static void destroy(void* pinst) | |
{ | |
((T*)pinst)->~T(); | |
// clear memory to help GC | |
memset(pinst, 0, sizeof(T)); | |
} | |
}; | |
void *p = _d_new(sizeof(T), &Dtor::destroy); | |
return new (p) T; | |
} | |
//........................................................................................ | |
// creates plain types use n > 1 to allocate an array | |
template <class T> | |
typename enable_if<!is_class<T>::value, T*>::type d_new(size_t n = 1) | |
{ | |
return static_cast<T*>(_d_new(sizeof(T) * n, NULL)); | |
} | |
#endif // D_NEW_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module bar; | |
import std.stdio; | |
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
extern(C++) | |
{ | |
interface Array | |
{ | |
void printInfo(); | |
size_t length(); | |
double* ptr(); | |
} | |
Array createArray(); | |
} | |
//........................................................................................ | |
Array useArray(Array array) | |
{ | |
double[] ary = array.ptr[0 .. array.length]; | |
writeln("array capacity ", ary.capacity); | |
ary[] = 1; | |
Array array2; | |
array2 = array; | |
return array2; | |
} | |
//........................................................................................ | |
void main() | |
{ | |
auto array = createArray(); | |
array.printInfo(); | |
writeln("array ", array.ptr[0 .. array.length]); | |
array = useArray(array); | |
// reference semantic | |
array.printInfo(); | |
writeln("array ", array.ptr[0 .. array.length]); | |
} |
well, but you have to do some kind of "injection" in the c++ source. will it be possible to call c++'s ctor/dtor without touching the c++ sources. I just want to use dmd and link to QtCore.dll.
g++ -g -c array.cpp -I/usr/local/include
dmd -g darray d_new array.o -L-lstdc++
./darray
dropped boost dependency
g++ -g -c -Wall array.cpp
dmd -g -w darray d_new array.o -L-lstdc++
./darray
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
gcc -c foo.cpp
dmd bar.d cpp_wrapper.d foo.o -L-lstdc++
./bar