Hello all.
Rikki Cattermole gave me this useful mixin, which can wrap a D class and create a "flattened" C ABI for it.
The issue is, trying to use:
pragma(mangle, "create_" ~ __traits(identifier, Type))
void* creator(Parameters!(Type.__ctor) args) {}
Doesn't actually seem to apply the mangling =/
I've also tried:
enum ConstructorName(Type) = "create_" ~ __traits(identifier, Type);
pragma(mangle, "create_" ~ ConstructorName!(Type))
void* creator(Parameters!(Type.__ctor) args) {}
To no success.
The source code I am using is:
import std;
// Try to use an enum to force comptime resolve
enum ConstructorName(Type) = "create_" ~ __traits(identifier, Type);
// Compile time mixin function that generates an "extern C" flattened ABI for a D class:
mixin template CWrapper(Type)
{
import std.traits;
export extern (C):
pragma(mangle, "create_" ~ __traits(identifier, Type))
void* creator(Parameters!(Type.__ctor) args)
{
return cast(void*) new Type(args);
}
mixin(() {
string ret;
foreach (m; __traits(allMembers, Type))
{
static if (m != "__ctor" && m != "__dtor" && isFunction!(__traits(getMember, Type, m)))
{
ret ~= `ReturnType!(__traits(getMember, Type, "` ~ m ~ `")) ` ~ __traits(identifier, Type) ~ `_` ~ m ~
`(void* obj, Parameters!(__traits(getMember, Type, "` ~ m ~ `")) args) { return (cast(Type)obj).` ~ m ~ `(args); }`;
}
}
return ret;
}());
}
// Sample class to generate C ABI for:
class Foo
{
int x;
this(int x) { this.x = x; }
int getX() { return x; }
void setX(int x) { this.x = x; }
}
mixin CWrapper!(Foo);
Running the below:
$ dmd -HC=verbose -HCf=main.h main.d
$ ldc2 --HC=verbose --HCf=main_ldc.h main.d
Gives the same issue -- the constructor is not mangled, it is emitted as creator()
:
// Automatically generated by LDC Compiler v2098
#pragma once
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <math.h>
#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template<typename T>
struct _d_dynamicArray final
{
size_t length;
T *ptr;
_d_dynamicArray() : length(0), ptr(NULL) { }
_d_dynamicArray(size_t length_in, T *ptr_in)
: length(length_in), ptr(ptr_in) { }
T& operator[](const size_t idx) {
assert(idx < length);
return ptr[idx];
}
const T& operator[](const size_t idx) const {
assert(idx < length);
return ptr[idx];
}
};
#endif
class Object;
// Ignored template main.ConstructorName(Type) because of linkage
// Ignored template main.CWrapper(Type) because of linkage
// Ignored class main.Foo because of linkage
extern "C" void* creator(int32_t _param_0);
extern "C" int32_t Foo_getX(void* obj);
extern "C" void Foo_setX(void* obj, int32_t _param_1);
extern "C" _d_dynamicArray< const char > Foo_toString(void* obj);
extern "C" Foo_toHash(void* obj);
extern "C" int32_t Foo_opCmp(void* obj, Object* _param_1);
extern "C" bool Foo_opEquals(void* obj, Object* _param_1);
extern "C" Object* Foo_factory(void* obj, _d_dynamicArray< const char > _param_1);