| 1 |
/* |
|---|
| 2 |
Copyright 2006, 2007 Kirk McDonald |
|---|
| 3 |
|
|---|
| 4 |
Permission is hereby granted, free of charge, to any person obtaining a copy of |
|---|
| 5 |
this software and associated documentation files (the "Software"), to deal in |
|---|
| 6 |
the Software without restriction, including without limitation the rights to |
|---|
| 7 |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|---|
| 8 |
of the Software, and to permit persons to whom the Software is furnished to do |
|---|
| 9 |
so, subject to the following conditions: |
|---|
| 10 |
|
|---|
| 11 |
The above copyright notice and this permission notice shall be included in all |
|---|
| 12 |
copies or substantial portions of the Software. |
|---|
| 13 |
|
|---|
| 14 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|---|
| 15 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|---|
| 16 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|---|
| 17 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|---|
| 18 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|---|
| 19 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|---|
| 20 |
SOFTWARE. |
|---|
| 21 |
*/ |
|---|
| 22 |
module pyd.def; |
|---|
| 23 |
|
|---|
| 24 |
import python; |
|---|
| 25 |
|
|---|
| 26 |
import pyd.func_wrap; |
|---|
| 27 |
import pyd.lib_abstract : |
|---|
| 28 |
symbolnameof, |
|---|
| 29 |
minArgs |
|---|
| 30 |
; |
|---|
| 31 |
//import meta.Default; |
|---|
| 32 |
//import meta.Nameof; |
|---|
| 33 |
|
|---|
| 34 |
private PyMethodDef module_global_methods[] = [ |
|---|
| 35 |
{ null, null, 0, null } |
|---|
| 36 |
]; |
|---|
| 37 |
|
|---|
| 38 |
private PyMethodDef[][string] module_methods; |
|---|
| 39 |
private PyObject*[string] pyd_modules; |
|---|
| 40 |
|
|---|
| 41 |
private void ready_module_methods(string modulename) { |
|---|
| 42 |
PyMethodDef empty; |
|---|
| 43 |
if (!(modulename in module_methods)) { |
|---|
| 44 |
module_methods[modulename] = (PyMethodDef[]).init; |
|---|
| 45 |
module_methods[modulename] ~= empty; |
|---|
| 46 |
} |
|---|
| 47 |
} |
|---|
| 48 |
|
|---|
| 49 |
PyObject* Pyd_Module_p(string modulename="") { |
|---|
| 50 |
PyObject** m = modulename in pyd_modules; |
|---|
| 51 |
if (m is null) return null; |
|---|
| 52 |
else return *m; |
|---|
| 53 |
} |
|---|
| 54 |
|
|---|
| 55 |
/** |
|---|
| 56 |
* Wraps a D function, making it callable from Python. |
|---|
| 57 |
* |
|---|
| 58 |
* Params: |
|---|
| 59 |
* name = The name of the function as it will appear in Python. |
|---|
| 60 |
* fn = The function to wrap. |
|---|
| 61 |
* MIN_ARGS = The minimum number of arguments this function can accept. |
|---|
| 62 |
* For use with functions with default arguments. Defaults to |
|---|
| 63 |
* the maximum number of arguments this function supports. |
|---|
| 64 |
* fn_t = The function type of the function to wrap. This must be |
|---|
| 65 |
* specified if more than one function shares the same name, |
|---|
| 66 |
* otherwise the first one defined lexically will be used. |
|---|
| 67 |
* |
|---|
| 68 |
* Examples: |
|---|
| 69 |
*$(D_CODE import pyd.pyd; |
|---|
| 70 |
*char[] foo(int i) { |
|---|
| 71 |
* if (i > 10) { |
|---|
| 72 |
* return "It's greater than 10!"; |
|---|
| 73 |
* } else { |
|---|
| 74 |
* return "It's less than 10!"; |
|---|
| 75 |
* } |
|---|
| 76 |
*} |
|---|
| 77 |
*extern (C) |
|---|
| 78 |
*export void inittestdll() { |
|---|
| 79 |
* _def!("foo", foo); |
|---|
| 80 |
* module_init("testdll"); |
|---|
| 81 |
*}) |
|---|
| 82 |
* And in Python: |
|---|
| 83 |
*$(D_CODE >>> import testdll |
|---|
| 84 |
*>>> print testdll.foo(20) |
|---|
| 85 |
*It's greater than 10!) |
|---|
| 86 |
*/ |
|---|
| 87 |
void def(alias fn, string name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS = minArgs!(fn, fn_t)) (string docstring="") { |
|---|
| 88 |
def!("", fn, name, fn_t, MIN_ARGS)(docstring); |
|---|
| 89 |
} |
|---|
| 90 |
|
|---|
| 91 |
void def(string modulename, alias fn, string name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS = minArgs!(fn, fn_t)) (string docstring) { |
|---|
| 92 |
pragma(msg, "def: " ~ name); |
|---|
| 93 |
PyMethodDef empty; |
|---|
| 94 |
ready_module_methods(modulename); |
|---|
| 95 |
PyMethodDef[]* list = &module_methods[modulename]; |
|---|
| 96 |
|
|---|
| 97 |
(*list)[length-1].ml_name = (name ~ \0).ptr; |
|---|
| 98 |
(*list)[length-1].ml_meth = &function_wrap!(fn, MIN_ARGS, fn_t).func; |
|---|
| 99 |
(*list)[length-1].ml_flags = METH_VARARGS; |
|---|
| 100 |
(*list)[length-1].ml_doc = (docstring ~ \0).ptr; |
|---|
| 101 |
(*list) ~= empty; |
|---|
| 102 |
} |
|---|
| 103 |
|
|---|
| 104 |
string pyd_module_name; |
|---|
| 105 |
|
|---|
| 106 |
/** |
|---|
| 107 |
* Module initialization function. Should be called after the last call to def. |
|---|
| 108 |
*/ |
|---|
| 109 |
PyObject* module_init(string docstring="") { |
|---|
| 110 |
//_loadPythonSupport(); |
|---|
| 111 |
string name = pyd_module_name; |
|---|
| 112 |
ready_module_methods(""); |
|---|
| 113 |
pyd_modules[""] = Py_InitModule3((name ~ \0).ptr, module_methods[""].ptr, (docstring ~ \0).ptr); |
|---|
| 114 |
return pyd_modules[""]; |
|---|
| 115 |
} |
|---|
| 116 |
|
|---|
| 117 |
/** |
|---|
| 118 |
* Module initialization function. Should be called after the last call to def. |
|---|
| 119 |
*/ |
|---|
| 120 |
PyObject* add_module(string name, string docstring="") { |
|---|
| 121 |
ready_module_methods(name); |
|---|
| 122 |
pyd_modules[name] = Py_InitModule3((name ~ \0).ptr, module_methods[name].ptr, (docstring ~ \0).ptr); |
|---|
| 123 |
return pyd_modules[name]; |
|---|
| 124 |
} |
|---|