Created
November 25, 2011 18:36
-
-
Save MartinNowak/1394145 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
import std.conv; | |
struct CppMangler | |
{ | |
CppMangler namespace(string name) | |
{ | |
return nested(name); | |
} | |
CppMangler klass(string name) | |
{ | |
return nested(name); | |
} | |
CppMangler meth(string name) | |
{ | |
assert(_nested); | |
_mangle ~= to!string(name.length) ~ name ~ "E"; | |
_nested = false; | |
return this; | |
} | |
CppMangler func(string name) | |
{ | |
assert(!_nested); | |
_mangle ~= to!string(name.length) ~ name; | |
return this; | |
} | |
CppMangler args(Args...)() | |
{ | |
/* ABI spec says: | |
* v void | |
* w wchar_t | |
* b bool | |
* c char | |
* a signed char | |
* h unsigned char | |
* s short | |
* t unsigned short | |
* i int | |
* j unsigned int | |
* l long | |
* m unsigned long | |
* x long long, __int64 | |
* y unsigned long long, __int64 | |
* n __int128 | |
* o unsigned __int128 | |
* f float | |
* d double | |
* e long double, __float80 | |
* g __float128 | |
* z ellipsis | |
* u <source-name> # vendor extended type | |
*/ | |
if (!Args.length) | |
_mangle ~= "v"; | |
foreach(Arg; Args) | |
{ | |
static if (is(Arg == bool)) | |
_mangle ~= "b"; | |
else static if (is(Arg == char)) | |
_mangle ~= "c"; | |
else static if (is(Arg == byte)) | |
_mangle ~= "a"; | |
else static if (is(Arg == ubyte)) | |
_mangle ~= "h"; | |
else static if (is(Arg == short)) | |
_mangle ~= "s"; | |
else static if (is(Arg == ushort)) | |
_mangle ~= "t"; | |
else static if (is(Arg == int)) | |
_mangle ~= "i"; | |
else static if (is(Arg == uint)) | |
_mangle ~= "j"; | |
else static if (is(Arg == sizediff_t)) | |
_mangle ~= "l"; | |
else static if (is(Arg == size_t)) | |
_mangle ~= "m"; | |
else static if (is(Arg == long)) | |
_mangle ~= "x"; | |
else static if (is(Arg == ulong)) | |
_mangle ~= "y"; | |
else static if (is(Arg == float)) | |
_mangle ~= "f"; | |
else static if (is(Arg == double)) | |
_mangle ~= "d"; | |
else static if (is(Arg == real)) | |
_mangle ~= "e"; | |
else | |
static assert(0, "Don't know how to mangle a " ~ Arg.stringof); | |
} | |
return this; | |
} | |
@property string get() const | |
{ | |
return _mangle; | |
} | |
@property ref string mangle() | |
{ | |
return _mangle; | |
} | |
private: | |
CppMangler nested(string name) | |
{ | |
if (!_nested) | |
_mangle ~= "N"; | |
_nested = true; | |
_mangle ~= to!string(name.length) ~ name; | |
return this; | |
} | |
version (OSX) | |
string _mangle="__Z"; | |
else | |
string _mangle="_Z"; | |
bool _nested; | |
} | |
template decl_cpp(string mangle, RT, Args...) | |
{ | |
mixin("alias " ~ mangle ~ " func;"); | |
} | |
unittest | |
{ | |
enum s1 = CppMangler().func("foo").args!()().get(); | |
enum s2 = CppMangler().klass("S").meth("bar").args!()().get(); | |
enum s3 = CppMangler().klass("S").meth("bari").args!(int)().get(); | |
enum s4 = CppMangler().klass("S").meth("ibar").args!()().get(); | |
enum s5 = CppMangler().namespace("baz").klass("S").meth("bar").args!()().get(); | |
enum s6 = CppMangler().namespace("baz").klass("S").meth("bari").args!(int)().get(); | |
enum s7 = CppMangler().namespace("baz").klass("S").meth("ibar").args!()().get(); | |
pragma(msg, s1); | |
pragma(msg, s2); | |
pragma(msg, s3); | |
pragma(msg, s4); | |
pragma(msg, s5); | |
pragma(msg, s6); | |
pragma(msg, s7); | |
// calls namespace baz { struct S { void bari(int i); }; }; | |
mixin("extern(C) void " ~ s6 ~ "(int);"); | |
mixin("alias "~s6~" baz_S_bari;"); | |
baz_S_bari(12); | |
} | |
void main() | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment