Created
April 24, 2012 07:28
-
-
Save lomereiter/2477467 to your computer and use it in GitHub Desktop.
d compile-time binding generation
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 cinterface; | |
import std.traits; | |
import std.string; | |
import std.conv; | |
import std.range; | |
import std.typetuple; | |
import std.algorithm; | |
import std.ascii; | |
// http://stackoverflow.com/questions/5630137/for-and-foreach-statements-in-d | |
template Iota(size_t a, size_t b) | |
{ | |
static if (a < b) { | |
alias TypeTuple!(a, Iota!(a + 1, b)) Iota; | |
} else { | |
alias TypeTuple!() Iota; | |
} | |
} | |
string fromCamelCase(string s) { | |
char res[]; | |
for (size_t i = 0; i < s.length; i++) { | |
auto c = s[i]; | |
if (isUpper(c)) { | |
if (res.length > 0 && | |
(!isUpper(s[i-1]) || | |
(i+1 < s.length && isLower(s[i+1])))) | |
{ | |
res ~= '_'; | |
} | |
res ~= toLower(c); | |
} else { | |
res ~= c; | |
} | |
} | |
return res.idup; | |
} | |
template makeCWrappers(T) { | |
static if(is(typeof(moduleName!T))) { | |
mixin("import " ~ moduleName!T ~ ";"); | |
} else { | |
mixin("import " ~ | |
fullyQualifiedName!(T)[0..fullyQualifiedName!(T).countUntil('.')] ~ | |
";"); // FIXME | |
} | |
string[] makeCWrappers() { | |
// TODO: check for __ctor and __dtor and process them separately | |
// in case any of these is not found, generate default T_new and T_destroy | |
// TODO: add conversions string <-> const char* (and other useful ones) | |
string[] methods; | |
foreach(m; __traits(allMembers, T)) { | |
enum method = fullyQualifiedName!(T) ~ "." ~ m; | |
enum underscore_m = fromCamelCase(m); | |
static if(is(ReturnType!(mixin(method)))) { | |
alias ReturnType!(mixin(method)) RetType; | |
alias ParameterTypeTuple!(mixin(method)) ParamTypes; | |
char[] params; | |
params ~= T.stringof.dup ~ "* p"; | |
// other parameters will be tmp0, tmp1, ... | |
foreach (i; Iota!(0, ParamTypes.length)) { | |
params ~= ", " ~ ParamTypes[i].stringof ~ " tmp".dup ~ to!string(i); | |
} | |
// generate return expression | |
char[] ret_expr; | |
ret_expr ~= "p." ~ m.dup ~ "("; | |
if (ParamTypes.length > 0) { | |
ret_expr ~= "tmp0".dup; | |
foreach (i; Iota!(1, ParamTypes.length)) { | |
ret_expr ~= ", tmp" ~ to!string(i); | |
} | |
} | |
ret_expr ~= ")".dup; | |
methods ~= "extern (C) " ~ RetType.stringof ~ ' ' ~ | |
toLower(T.stringof) ~ '_' ~ underscore_m ~ | |
"(" ~ params.idup ~ ")" ~ | |
"{ " ~ (RetType.stringof != "void" ? "return " : "") ~ | |
ret_expr.idup ~ "; }"; | |
} | |
} | |
return methods; | |
} | |
} | |
template makeCInterface(T) { | |
string makeCInterface() { | |
char[] result; | |
foreach (decl; makeCWrappers!T) { | |
result ~= decl.dup ~ "\n"; | |
} | |
return result.idup; | |
} | |
} |
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 foo; | |
import std.stdio; | |
public struct Foo { | |
public double foo(string boo, Foo foo) { | |
return boo.length * foo.moo(); | |
} | |
public int moo() { | |
return 42; | |
} | |
public void bar(string name) { | |
writeln("hello, " ~ name ~ "!"); | |
} | |
} | |
import cinterface; | |
// dmd foo.d cinterface.d -shared -offoo.so | |
// nm -D foo.so | grep foo will show generated functions :-) | |
mixin(makeCInterface!Foo); | |
void main() { | |
writeln(makeCInterface!File); | |
writeln(makeCInterface!Foo); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment