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