1 // Copyright (c) Lawrence Livermore National Security, LLC and other Conduit
2 // Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
3 // other details. No copyright assignment is required to contribute to Conduit.
4
5
6 //-----------------------------------------------------------------------------
7 // -- Python includes (these must be included first) --
8 //-----------------------------------------------------------------------------
9 #include <Python.h>
10 #include <structmember.h>
11 #include "bytesobject.h"
12
13 #if PY_MAJOR_VERSION >= 3
14 #define IS_PY3K
15 #endif
16
17 // use proper strdup
18 #ifdef CONDUIT_PLATFORM_WINDOWS
19 #define _conduit_strdup _strdup
20 #else
21 #define _conduit_strdup strdup
22 #endif
23
24 //-----------------------------------------------------------------------------
25 // -- standard lib includes --
26 //-----------------------------------------------------------------------------
27 #include <iostream>
28 #include <vector>
29
30 //---------------------------------------------------------------------------//
31 // conduit includes
32 //---------------------------------------------------------------------------//
33 #include "conduit.hpp"
34 #include "conduit_relay.hpp"
35 #include "conduit_relay_python_exports.h"
36
37 // conduit python module capi header
38 #include "conduit_python.hpp"
39
40 using namespace conduit;
41
42 //---------------------------------------------------------------------------//
43 // conduit::relay::about
44 //---------------------------------------------------------------------------//
45 static PyObject *
PyRelay_about()46 PyRelay_about()
47 {
48 //create and return a node with the result of about
49 PyObject *py_node_res = PyConduit_Node_Python_Create();
50 Node *node = PyConduit_Node_Get_Node_Ptr(py_node_res);
51 conduit::relay::about(*node);
52 return (PyObject*)py_node_res;
53 }
54
55 //---------------------------------------------------------------------------//
56 // Python Module Method Defs
57 //---------------------------------------------------------------------------//
58 static PyMethodDef relay_python_funcs[] =
59 {
60 //-----------------------------------------------------------------------//
61 {"about",
62 (PyCFunction)PyRelay_about,
63 METH_NOARGS,
64 NULL},
65 //-----------------------------------------------------------------------//
66 // end relay methods table
67 //-----------------------------------------------------------------------//
68 {NULL, NULL, METH_VARARGS, NULL}
69 };
70
71 //---------------------------------------------------------------------------//
72 //---------------------------------------------------------------------------//
73 // Module Init Code
74 //---------------------------------------------------------------------------//
75 //---------------------------------------------------------------------------//
76
77 struct module_state {
78 PyObject *error;
79 };
80
81 //---------------------------------------------------------------------------//
82 #if defined(IS_PY3K)
83 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
84 #else
85 #define GETSTATE(m) (&_state)
86 static struct module_state _state;
87 #endif
88 //---------------------------------------------------------------------------//
89
90 //---------------------------------------------------------------------------//
91 // Extra Module Setup Logic for Python3
92 //---------------------------------------------------------------------------//
93 #if defined(IS_PY3K)
94 //---------------------------------------------------------------------------//
95 static int
relay_python_traverse(PyObject * m,visitproc visit,void * arg)96 relay_python_traverse(PyObject *m, visitproc visit, void *arg)
97 {
98 Py_VISIT(GETSTATE(m)->error);
99 return 0;
100 }
101
102 //---------------------------------------------------------------------------//
103 static int
relay_python_clear(PyObject * m)104 relay_python_clear(PyObject *m)
105 {
106 Py_CLEAR(GETSTATE(m)->error);
107 return 0;
108 }
109
110 //---------------------------------------------------------------------------//
111 static struct PyModuleDef relay_python_module_def =
112 {
113 PyModuleDef_HEAD_INIT,
114 "relay_python",
115 NULL,
116 sizeof(struct module_state),
117 relay_python_funcs,
118 NULL,
119 relay_python_traverse,
120 relay_python_clear,
121 NULL
122 };
123
124
125 #endif
126
127 //---------------------------------------------------------------------------//
128 // The module init function signature is different between py2 and py3
129 // This macro simplifies the process of returning when an init error occurs.
130 //---------------------------------------------------------------------------//
131 #if defined(IS_PY3K)
132 #define PY_MODULE_INIT_RETURN_ERROR return NULL
133 #else
134 #define PY_MODULE_INIT_RETURN_ERROR return
135 #endif
136 //---------------------------------------------------------------------------//
137
138
139 //---------------------------------------------------------------------------//
140 // Main entry point
141 //---------------------------------------------------------------------------//
142 extern "C"
143 //---------------------------------------------------------------------------//
144 #if defined(IS_PY3K)
PyInit_conduit_relay_python(void)145 CONDUIT_RELAY_PYTHON_API PyObject * PyInit_conduit_relay_python(void)
146 #else
147 CONDUIT_RELAY_PYTHON_API void initconduit_relay_python(void)
148 #endif
149 //---------------------------------------------------------------------------//
150 {
151 //-----------------------------------------------------------------------//
152 // create our main module
153 //-----------------------------------------------------------------------//
154
155 #if defined(IS_PY3K)
156 PyObject *relay_module = PyModule_Create(&relay_python_module_def);
157 #else
158 PyObject *relay_module = Py_InitModule((char*)"conduit_relay_python",
159 relay_python_funcs);
160 #endif
161
162
163 if(relay_module == NULL)
164 {
165 PY_MODULE_INIT_RETURN_ERROR;
166 }
167
168 struct module_state *st = GETSTATE(relay_module);
169
170 st->error = PyErr_NewException((char*)"conduit_relay_python.Error",
171 NULL,
172 NULL);
173 if (st->error == NULL)
174 {
175 Py_DECREF(relay_module);
176 PY_MODULE_INIT_RETURN_ERROR;
177 }
178
179 // setup for conduit python c api
180 if(import_conduit() < 0)
181 {
182 PY_MODULE_INIT_RETURN_ERROR;
183 }
184
185
186 #if defined(IS_PY3K)
187 return relay_module;
188 #endif
189
190 }
191
192