1 module python.wrap.wrap;
2 
3 /// For a nicer API
4 struct Module {
5     string name;
6 }
7 
8 
9 /// For a nicer API
10 struct CFunctions(functions...) {
11     alias symbols = functions;
12     enum length = functions.length;
13 
14     static string stringifySymbols() {
15         import std.array: join;
16 
17         string[] ret;
18 
19         static foreach(cfunction; symbols)
20             ret ~= __traits(identifier, cfunction);
21 
22         return ret.join(", ");
23     }
24 }
25 
26 /// A list of aggregates to wrap
27 struct Aggregates(T...) {
28     alias Types = T;
29 
30     static string stringifyTypes() {
31         import std.array: join;
32         string[] ret;
33 
34         static foreach(T; Types)
35             ret ~= T.stringof;
36 
37         return ret.join(", ");
38     }
39 }
40 
41 
42 /**
43    A string mixin to reduce boilerplate when creating a Python module.
44    Takes a module name and a variadic list of C functions to make
45    available.
46  */
47 string createModuleMixin(Module module_, alias cfunctions, alias aggregates)()
48     if(isPython3)
49 {
50     import std.format: format;
51 
52     enum ret = q{
53         // This is declared as an extern C variable in python.bindings.
54         // We declare it here to avoid linker errors.
55         export __gshared extern(C) PyDateTime_CAPI* PyDateTimeAPI;
56 
57         import python: ModuleInitRet;
58 
59         extern(C) export ModuleInitRet PyInit_%s() {
60             import python: pyDateTimeImport;
61             pyDateTimeImport;
62             return createModule!(
63                 Module("%s"),
64                 CFunctions!(
65                     %s
66                 ),
67                 Aggregates!(
68                     %s
69                 )
70             );
71         }
72     }.format(module_.name, module_.name, cfunctions.stringifySymbols, aggregates.stringifyTypes);
73 
74     return ret;
75 }
76 
77 string createModuleMixin(Module module_, alias cfunctions, alias aggregates)()
78     if(isPython2)
79 {
80     import std.format: format;
81 
82     enum ret = q{
83         // This is declared as an extern C variable in python.bindings.
84         // We declare it here to avoid linker errors.
85         export __gshared extern(C) PyDateTime_CAPI* PyDateTimeAPI;
86 
87         extern(C) export void init%s() {
88             import python: pyDateTimeImport, initModule;
89             pyDateTimeImport;
90             initModule!(
91                 Module("%s"),
92                 CFunctions!(
93                     %s
94                 ),
95                 Aggregates!(
96                     %s
97                 ),
98             );
99         }
100     }.format(module_.name, module_.name, cfunctions.stringifySymbols, aggregates.stringifyTypes);
101 
102     return ret;
103 }