1 module pybuffer; 2 3 import std.stdio; 4 import mir.ndslice; 5 6 7 struct pybuffer {} 8 9 mixin template MixinPyBufferWrappers(string _Impl = __MODULE__) { 10 private enum string _generated = { 11 mixin("import Impl = " ~ _Impl ~ ";"); 12 import std.conv : to; 13 import std.traits : Parameters, ReturnType; 14 string ret; 15 foreach (mem; __traits(allMembers, Impl)) { 16 foreach (attr; __traits(getAttributes, __traits(getMember, Impl, mem))) { 17 if (is(attr == pybuffer)) { 18 pragma(msg, mem); 19 mixin("alias R = ReturnType!(" ~ _Impl ~ "." ~ mem ~ ");"); 20 static assert(is(R == void), "@pybuffer function should return void"); 21 string args; 22 string rargs; 23 string converts = " import mir.ndslice.connect.cpython;\n"; 24 converts ~= " import std.stdio : writeln;\n"; 25 26 mixin("alias Ps = Parameters!(" ~ _Impl ~ "." ~ mem ~ ");"); 27 foreach (i, P; Ps) { 28 pragma(msg, P.stringof); 29 enum a = "a" ~ i.to!string; 30 if (isSlice!P) { 31 args ~= " " ~ "ref Py_buffer " ~ a ~ " ,"; 32 enum _a = "_a" ~ i.to!string; 33 converts ~= " " ~ P.stringof ~ " " ~ _a ~ ";\n"; 34 converts ~= " {\n auto err = fromPythonBuffer( " ~ _a ~ " , " ~ a ~ " );\n"; 35 // TODO: enrich error messages 36 converts ~= " if (err != PythonBufferErrorCode.success) { writeln(err, \" at param " ~ i.to!string ~ " \", a" ~ i.to!string ~ "); return err; }\n }\n"; 37 rargs ~= " " ~ _a ~ " ,"; 38 } else { 39 args ~= " " ~ P.stringof ~ " " ~ a ~ " ,"; 40 rargs ~= " " ~ a ~ " ,"; 41 } 42 } 43 44 // decleration 45 enum newName = "pybuffer_" ~ mem; 46 // workaround to https://issues.dlang.org/show_bug.cgi?id=12575 47 ret ~= "pragma(mangle, __traits(identifier, " ~ newName ~ "))\n"; 48 ret ~= "extern(C) auto " ~ newName ~ "(" ~ args[0..$-1] ~ ") {\n"; 49 50 // conversions: pybuf -> ndslice 51 ret ~= converts; 52 53 // exec function 54 ret ~= " " ~ _Impl ~ "." ~ mem ~ "(" ~ rargs[0..$-1] ~ ");\n"; 55 56 // return success 57 ret ~= " return PythonBufferErrorCode.success;\n}\n\n"; 58 } 59 } 60 } 61 return ret; 62 }(); 63 64 pragma(mangle, __traits(identifier, print_generated)) 65 extern(C) void print_generated() { 66 write(_generated); 67 } 68 69 mixin(_generated); 70 }