~durga/maus/rel709

« back to all changes in this revision

Viewing changes to src/py_cpp/PyMiceModule.cc

  • Committer: Durga Rajaram
  • Date: 2013-10-01 00:19:57 UTC
  • mfrom: (659.1.74 rc)
  • Revision ID: durga@fnal.gov-20131001001957-iswih60vis9rodw0
Tags: MAUS-v0.7.1
MAUS-v0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus
 
2
 *
 
3
 * MAUS is free software: you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation, either version 3 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * MAUS is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with MAUS.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 */
 
17
 
 
18
// These ifdefs are required to avoid cpp compiler warning
 
19
#ifdef _POSIX_C_SOURCE
 
20
#undef _POSIX_C_SOURCE
 
21
#endif
 
22
 
 
23
#ifdef _XOPEN_SOURCE
 
24
#undef _XOPEN_SOURCE
 
25
#endif
 
26
 
 
27
#include <Python.h>
 
28
#include <structmember.h>
 
29
 
 
30
#include <string.h>
 
31
#include <ctype.h>
 
32
 
 
33
#include <sstream>
 
34
#include <vector>
 
35
 
 
36
#include "src/legacy/Config/MiceModule.hh"
 
37
 
 
38
#include "src/common_cpp/Utils/Exception.hh"
 
39
 
 
40
#define MAUS_PYMICEMODULE_CC
 
41
#include "src/py_cpp/PyMiceModule.hh"
 
42
#undef MAUS_PYMICEMODULE_CC
 
43
 
 
44
namespace MAUS {
 
45
namespace PyMiceModule {
 
46
 
 
47
 
 
48
std::string get_name_docstring =
 
49
std::string("Get the name of this MiceModule\n\n")+
 
50
std::string("  Takes no arguments.\n")+
 
51
std::string("Returns a python string containing the module name.");
 
52
 
 
53
PyObject *get_name(PyObject* self, PyObject *args, PyObject *kwds) {
 
54
    MiceModule* mod = C_API::get_mice_module(self);
 
55
    PyObject* py_string = PyString_FromString(mod->name().c_str());
 
56
    Py_INCREF(py_string);
 
57
    return py_string;
 
58
}
 
59
 
 
60
std::string get_property_docstring =
 
61
std::string("Returns the value of a particular MiceModule property\n\n")+
 
62
std::string("  - name (string) name of the property\n")+
 
63
std::string("  - type (string) type of the property\n")+
 
64
std::string("Returns a value of the appropriate type");
 
65
 
 
66
PyObject* get_bool(MiceModule* mod, std::string name) {
 
67
    try {
 
68
        bool out = mod->propertyBoolThis(name);
 
69
        int out_int = out ? 1 : 0; //  ooh I feel so dirty
 
70
        PyObject* py_out = Py_BuildValue("b", out_int);
 
71
        Py_INCREF(py_out);
 
72
        return py_out;
 
73
    } catch(std::exception& exc) {
 
74
        PyErr_SetString(PyExc_KeyError, (&exc)->what());
 
75
        return NULL;
 
76
    }
 
77
}
 
78
 
 
79
PyObject* get_int(MiceModule* mod, std::string name) {
 
80
    try {
 
81
        int out = mod->propertyIntThis(name);
 
82
        PyObject* py_out = Py_BuildValue("i", out);
 
83
        Py_INCREF(py_out);
 
84
        return py_out;
 
85
    } catch(std::exception& exc) {
 
86
        PyErr_SetString(PyExc_KeyError, (&exc)->what());
 
87
        return NULL;
 
88
    }
 
89
}
 
90
 
 
91
PyObject* get_double(MiceModule* mod, std::string name) {
 
92
    try {
 
93
        double out = mod->propertyDoubleThis(name);
 
94
        PyObject* py_out = Py_BuildValue("d", out);
 
95
        Py_INCREF(py_out);
 
96
        return py_out;
 
97
    } catch(std::exception& exc) {
 
98
        PyErr_SetString(PyExc_KeyError, (&exc)->what());
 
99
        return NULL;
 
100
    }
 
101
}
 
102
 
 
103
PyObject* get_string(MiceModule* mod, std::string name) {
 
104
    try {
 
105
        std::string out = mod->propertyStringThis(name);
 
106
        PyObject* py_out = Py_BuildValue("s", out.c_str());
 
107
        Py_INCREF(py_out);
 
108
        return py_out;
 
109
    } catch(std::exception& exc) {
 
110
        PyErr_SetString(PyExc_KeyError, (&exc)->what());
 
111
        return NULL;
 
112
    }
 
113
}
 
114
 
 
115
PyObject* get_hep3vector(MiceModule* mod, std::string name) {
 
116
    try {
 
117
        CLHEP::Hep3Vector out = mod->propertyHep3VectorThis(name);
 
118
        PyObject* py_out = PyDict_New();
 
119
        Py_INCREF(py_out);
 
120
        PyObject* x = Py_BuildValue("d", out[0]);
 
121
        Py_INCREF(x);
 
122
        PyObject* y = Py_BuildValue("d", out[1]);
 
123
        Py_INCREF(y);
 
124
        PyObject* z = Py_BuildValue("d", out[2]);
 
125
        Py_INCREF(z);
 
126
        PyDict_SetItemString(py_out, "x", x);
 
127
        PyDict_SetItemString(py_out, "y", y);
 
128
        PyDict_SetItemString(py_out, "z", z);
 
129
        return py_out;
 
130
    } catch(std::exception& exc) {
 
131
        PyErr_SetString(PyExc_KeyError, (&exc)->what());
 
132
        return NULL;
 
133
    }
 
134
}
 
135
 
 
136
PyObject *get_property(PyObject* self, PyObject *args, PyObject *kwds) {
 
137
    MiceModule* mod = C_API::get_mice_module(self);
 
138
    if (mod == NULL) {
 
139
        PyErr_SetString(PyExc_TypeError,
 
140
                        "MiceModule was not properly initialised");
 
141
        return NULL;
 
142
    }
 
143
    const char* name = NULL;
 
144
    const char* c_type = NULL;
 
145
    static char *kwlist[] = {const_cast<char*>("name"),
 
146
                             const_cast<char*>("type"), NULL};
 
147
    if (!PyArg_ParseTupleAndKeywords
 
148
                                  (args, kwds, "ss|", kwlist, &name, &c_type)) {
 
149
        return NULL;
 
150
    }
 
151
    // convert type to lower case
 
152
    std::string type(c_type);
 
153
    for (size_t i = 0; i < type.size(); ++i) {
 
154
        type[i] = std::tolower(type[i]);
 
155
    }
 
156
 
 
157
    if (type == "bool" || type == "boolean") {
 
158
        return get_bool(mod, name);
 
159
    } else if (type == "int") {
 
160
        return get_int(mod, name);
 
161
    } else if (type == "string") {
 
162
        return get_string(mod, name);
 
163
    } else if (type == "double") {
 
164
        return get_double(mod, name);
 
165
    } else if (type == "hep3vector") {
 
166
        return get_hep3vector(mod, name);
 
167
    } else {
 
168
        std::stringstream message;
 
169
        message << "Did not recognise type '" << type << "' ";
 
170
        message << " - should be one of bool, int, string, double, hep3vector";
 
171
        PyErr_SetString(PyExc_TypeError, message.str().c_str());
 
172
        return NULL;
 
173
    }
 
174
}
 
175
 
 
176
bool set_property_hep3vector_one
 
177
                          (PyObject* py_dict, std::string dim, double* value) {
 
178
    //  py_value is borrowed ref
 
179
    PyObject* py_value = PyDict_GetItemString(py_dict, dim.c_str());
 
180
    if (!py_value) {
 
181
        PyErr_SetString(PyExc_KeyError,
 
182
                      "could not find x, y and z in hep3vector dictionary");
 
183
        return false;
 
184
    }
 
185
    if (!PyArg_Parse(py_value, "d", value)) {
 
186
        std::string err = "value['"+dim+"'] could not be converted to a number";
 
187
        PyErr_SetString(PyExc_TypeError, err.c_str());
 
188
        return false;
 
189
    }
 
190
    return true;
 
191
}
 
192
 
 
193
PyObject* set_property_hep3vector
 
194
                      (MiceModule* mod, std::string name, PyObject* py_value) {
 
195
    CLHEP::Hep3Vector value;
 
196
    if (!PyDict_Check(py_value)) {
 
197
        PyErr_SetString(PyExc_TypeError,
 
198
                        "Failed to resolve Hep3Vector as a dict");
 
199
        return NULL;
 
200
    }
 
201
    if (!set_property_hep3vector_one(py_value, "x", &value[0])) return NULL;
 
202
    if (!set_property_hep3vector_one(py_value, "y", &value[1])) return NULL;
 
203
    if (!set_property_hep3vector_one(py_value, "z", &value[2])) return NULL;
 
204
    mod->setProperty(name, value);
 
205
    Py_INCREF(Py_None);
 
206
    return Py_None;  // all is well
 
207
}
 
208
 
 
209
std::string set_property_docstring =
 
210
std::string("Sets the value of a particular MiceModule property\n\n")+
 
211
std::string("  - name (string) name of the property\n")+
 
212
std::string("  - type (string) type of the property\n")+
 
213
std::string("  - value (type) value to be set - should be convertible to\n")+
 
214
std::string("    the appropriate type\n")+
 
215
std::string("Returns None");
 
216
 
 
217
PyObject *set_property(PyObject* self, PyObject *args, PyObject *kwds) {
 
218
    MiceModule* mod = C_API::get_mice_module(self);
 
219
    if (mod == NULL) {
 
220
        PyErr_SetString(PyExc_TypeError,
 
221
                        "MiceModule was not properly initialised");
 
222
        return NULL;
 
223
    }
 
224
    const char* name = NULL;
 
225
    const char* c_type = NULL;
 
226
    PyObject* py_value = NULL;
 
227
    static char *kwlist[] = {const_cast<char*>("name"),
 
228
                             const_cast<char*>("type"),
 
229
                             const_cast<char*>("value"), NULL};
 
230
    if (!PyArg_ParseTupleAndKeywords
 
231
                      (args, kwds, "ssO|", kwlist, &name, &c_type, &py_value)) {
 
232
        return NULL;
 
233
    }
 
234
    // convert type to lower case
 
235
    std::string type(c_type);
 
236
    for (size_t i = 0; i < type.size(); ++i) {
 
237
        type[i] = std::tolower(type[i]);
 
238
    }
 
239
 
 
240
    if (type == "bool" || type == "boolean") {
 
241
        int value = 0;
 
242
        if (PyArg_Parse(py_value, "i", &value))
 
243
            mod->setProperty(name, value != 0);
 
244
        else
 
245
            return NULL;
 
246
    } else if (type == "int") {
 
247
        int value = 0;
 
248
        if (PyArg_Parse(py_value, "i", &value))
 
249
            mod->setProperty(name, value);
 
250
        else
 
251
            return NULL;
 
252
    } else if (type == "string") {
 
253
        char* value = NULL;
 
254
        if (PyArg_Parse(py_value, "s", &value))
 
255
            mod->setProperty(name, std::string(value));
 
256
        else
 
257
            return NULL;
 
258
    } else if (type == "double") {
 
259
        double value = 0;
 
260
        if (PyArg_Parse(py_value, "d", &value))
 
261
            mod->setProperty(name, value);
 
262
        else
 
263
            return NULL;
 
264
    } else if (type == "hep3vector") {
 
265
        return set_property_hep3vector(mod, name, py_value);
 
266
    } else {
 
267
        std::stringstream message;
 
268
        message << "Did not recognise type '" << type << "' ";
 
269
        message << " - should be one of bool, int, string, double, hep3vector";
 
270
        PyErr_SetString(PyExc_TypeError, message.str().c_str());
 
271
        return NULL;
 
272
    }
 
273
    Py_INCREF(Py_None);
 
274
    return Py_None;
 
275
}
 
276
 
 
277
std::string get_children_docstring =
 
278
std::string("Get child modules of this MiceModule\n\n")+
 
279
std::string("  Takes no arguments.\n")+
 
280
std::string("Returns a python list containing a deep copy of all child\n")+
 
281
std::string("MiceModules.");
 
282
 
 
283
PyObject *get_children(PyObject* self, PyObject *args, PyObject *kwds) {
 
284
    MiceModule* mod = C_API::get_mice_module(self);
 
285
    std::vector<MiceModule*> daughter_list = mod->allDaughters();
 
286
    PyObject* py_list = PyList_New(daughter_list.size());
 
287
    Py_INCREF(py_list);
 
288
    for (size_t i = 0; i < daughter_list.size(); ++i) {
 
289
        if (daughter_list[i] == NULL) {
 
290
            PyErr_SetString(PyExc_RuntimeError, "Could not find MiceModule");
 
291
            return NULL;
 
292
        }
 
293
        PyObject* py_mod = C_API::create_empty_module();
 
294
        Py_INCREF(py_mod);
 
295
        MiceModule* new_child = MiceModule::deepCopy(*daughter_list[i], false);
 
296
        C_API::set_mice_module(py_mod, new_child);
 
297
        PyList_SetItem(py_list, i, py_mod);
 
298
    }
 
299
    return py_list;
 
300
}
 
301
 
 
302
 
 
303
bool will_circle(const MiceModule* ancestor, const MiceModule* child) {
 
304
    if (ancestor == NULL)
 
305
        return false;
 
306
    else if (ancestor == child)
 
307
        return true;
 
308
    else
 
309
        return will_circle(ancestor->mother(), child);
 
310
}
 
311
 
 
312
std::string set_children_docstring =
 
313
std::string("Set child modules of this MiceModule\n\n")+
 
314
std::string("  - children (list) list of MiceModule objects. The existing\n")+
 
315
std::string("  children will be replaced by deep copies of those in the\n")+
 
316
std::string("  list. The parent module of the children is updated to this\n")+
 
317
std::string("  MiceModule.\n")+
 
318
std::string("Returns None.");
 
319
 
 
320
PyObject *set_children(PyObject* self, PyObject *args, PyObject *kwds) {
 
321
    MiceModule* mod = C_API::get_mice_module(self);
 
322
    if (mod == NULL)
 
323
        return NULL;
 
324
 
 
325
    PyObject* py_children = NULL;
 
326
    static char *kwlist[] = {const_cast<char*>("children"), NULL};
 
327
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|", kwlist, &py_children)) {
 
328
        return NULL;
 
329
    }
 
330
    if (!PyList_Check(py_children)) {
 
331
        PyErr_SetString(PyExc_TypeError, "Argument should be a list");
 
332
        return NULL;
 
333
    }
 
334
    std::vector<MiceModule*> children;
 
335
    for (int i = 0; i < PyList_Size(py_children); ++i) {
 
336
        PyObject* py_child = PyList_GetItem(py_children, i);
 
337
        MiceModule* child = C_API::get_mice_module(py_child);
 
338
        if (child == NULL) {
 
339
            PyErr_SetString(PyExc_TypeError,
 
340
                            "List object was not a MiceModule");
 
341
            return NULL;  // no memory allocated and module unchanged
 
342
        }
 
343
        children.push_back(MiceModule::deepCopy(*child, false));
 
344
    }
 
345
    while (mod->allDaughters().size() > 0) {
 
346
        mod->allDaughters()[0]->setMother(NULL);
 
347
        delete mod->allDaughters()[0];
 
348
        mod->removeDaughter(mod->allDaughters()[0]);
 
349
    }
 
350
    for (size_t i = 0; i < children.size(); ++i) {
 
351
        mod->addDaughter(children[i]);
 
352
        children[i]->setMother(mod);
 
353
    }
 
354
 
 
355
    Py_INCREF(Py_None);
 
356
    return Py_None;
 
357
}
 
358
 
 
359
PyObject *_alloc(PyTypeObject *type, Py_ssize_t nitems) {
 
360
    void* void_mod = malloc(sizeof(PyMiceModule));
 
361
    PyMiceModule* mod = reinterpret_cast<PyMiceModule*>(void_mod);
 
362
    mod->mod = NULL;
 
363
    mod->ob_refcnt = 1;
 
364
    mod->ob_type = type;
 
365
    return reinterpret_cast<PyObject*>(mod);
 
366
}
 
367
 
 
368
int _init(PyObject* self, PyObject *args, PyObject *kwds) {
 
369
    PyMiceModule* mod = reinterpret_cast<PyMiceModule*>(self);
 
370
    // failed to cast or self was not initialised - something horrible happened
 
371
    if (mod == NULL) {
 
372
        PyErr_SetString(PyExc_TypeError,
 
373
                        "Failed to resolve self as PyMiceModule in __init__");
 
374
        return -1;
 
375
    }
 
376
    // legal python to call initialised_object.__init__() to reinitialise, so
 
377
    // handle this case
 
378
    if (mod->mod != NULL) {
 
379
        delete mod->mod;
 
380
    }
 
381
    char* file_name;
 
382
    static char *kwlist[] = {const_cast<char*>("file_name"), NULL};
 
383
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, &file_name)) {
 
384
        return -1;
 
385
    }
 
386
 
 
387
    try {
 
388
        mod->mod = new MiceModule(std::string(file_name));
 
389
    } catch(std::exception& exc) {
 
390
        PyErr_SetString(PyExc_ValueError, (&exc)->what());
 
391
        return -1;
 
392
    }
 
393
    return 0;
 
394
}
 
395
 
 
396
void _free(PyMiceModule * self) {
 
397
    if (self != NULL) {
 
398
        if (self->mod != NULL && self->mod->mother() == NULL)
 
399
            delete self->mod;
 
400
        free(self);
 
401
    }
 
402
}
 
403
 
 
404
PyObject* _str(PyObject * self) {
 
405
    MiceModule* mod = C_API::get_mice_module(self);
 
406
    if (mod == NULL) {
 
407
        PyErr_SetString(PyExc_TypeError,
 
408
                        "MiceModule was not properly initialised");
 
409
        return NULL;
 
410
    }
 
411
    std::stringstream ss_in;
 
412
    mod->printThis(ss_in);
 
413
    return PyString_FromString(ss_in.str().c_str());
 
414
}
 
415
 
 
416
const char* module_docstring =
 
417
  "mice_module for geometry and field definitions including MiceModule class";
 
418
 
 
419
std::string class_docstring_str =
 
420
std::string("MiceModule provides bindings for defining geometries.\n\n")+
 
421
std::string("\n")+
 
422
std::string("MiceModules are representations of the MAUS geometry and.\n")+
 
423
std::string("fields. They are structured as a tree; for now the tree is\n")+
 
424
std::string("mono-directional. Each level of the tree holds properties that\n")+
 
425
std::string("reflect the geometry objects at that level and child modules\n")+
 
426
std::string("that can be used to access lower level geometry objects. \n")+
 
427
std::string("\n")+
 
428
std::string("See MAUS documentation chapter \"How to Define a Geometry\".\n")+
 
429
std::string("\n")+
 
430
std::string("__init__(file_name)\n")+
 
431
std::string("  Constructor for a new MiceModule.\n")+
 
432
std::string("    - file_name (string) name of the file from which to read\n")+
 
433
std::string("    the MiceModule file. Either a path relative to the current\n")+
 
434
std::string("    directory or relative to the")+
 
435
std::string("         ${MICEFILES}/Models/Configurations/\n")+
 
436
std::string("    environment variable\n")+
 
437
std::string("  Returns a MiceModule object\n");
 
438
const char* class_docstring = class_docstring_str.c_str();
 
439
 
 
440
static PyMemberDef _members[] = {
 
441
{NULL}
 
442
};
 
443
 
 
444
static PyMethodDef _methods[] = {
 
445
{"get_name", (PyCFunction)get_name,
 
446
  METH_VARARGS|METH_KEYWORDS, get_name_docstring.c_str()},
 
447
{"set_children", (PyCFunction)set_children,
 
448
  METH_VARARGS|METH_KEYWORDS, set_children_docstring.c_str()},
 
449
{"get_children", (PyCFunction)get_children,
 
450
  METH_VARARGS|METH_KEYWORDS, get_children_docstring.c_str()},
 
451
{"get_property", (PyCFunction)get_property,
 
452
  METH_VARARGS|METH_KEYWORDS, get_property_docstring.c_str()},
 
453
{"set_property", (PyCFunction)set_property,
 
454
  METH_VARARGS|METH_KEYWORDS, set_property_docstring.c_str()},
 
455
{NULL}
 
456
};
 
457
 
 
458
static PyTypeObject PyMiceModuleType = {
 
459
    PyObject_HEAD_INIT(NULL)
 
460
    0,                         /*ob_size*/
 
461
    "mice_module.MiceModule",         /*tp_name*/
 
462
    sizeof(PyMiceModule),           /*tp_basicsize*/
 
463
    0,                         /*tp_itemsize*/
 
464
    (destructor)_free, /*tp_dealloc*/
 
465
    0,                         /*tp_print*/
 
466
    0,                         /*tp_getattr*/
 
467
    0,                         /*tp_setattr*/
 
468
    0,                         /*tp_compare*/
 
469
    _str,                      /*tp_repr*/
 
470
    0,                         /*tp_as_number*/
 
471
    0,                         /*tp_as_sequence*/
 
472
    0,                         /*tp_as_mapping*/
 
473
    0,                         /*tp_hash */
 
474
    0,                         /*tp_call*/
 
475
    _str,                      /*tp_str*/
 
476
    0,                         /*tp_getattro*/
 
477
    0,                         /*tp_setattro*/
 
478
    0,                         /*tp_as_buffer*/
 
479
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
 
480
    class_docstring,           /* tp_doc */
 
481
    0,                         /* tp_traverse */
 
482
    0,                         /* tp_clear */
 
483
    0,                         /* tp_richcompare */
 
484
    0,                         /* tp_weaklistoffset */
 
485
    0,                         /* tp_iter */
 
486
    0,                         /* tp_iternext */
 
487
    _methods,           /* tp_methods */
 
488
    _members,           /* tp_members */
 
489
    0,                         /* tp_getset */
 
490
    0,                         /* tp_base */
 
491
    0,                         /* tp_dict */
 
492
    0,                         /* tp_descr_get */
 
493
    0,                         /* tp_descr_set */
 
494
    0,                         /* tp_dictoffset */
 
495
    (initproc)_init,      /* tp_init */
 
496
    (allocfunc)_alloc,    /* tp_alloc, called by new */
 
497
    PyType_GenericNew,                  /* tp_new */
 
498
    (freefunc)_free, /* tp_free, called by dealloc */
 
499
};
 
500
 
 
501
 
 
502
static PyMethodDef _keywdarg_methods[] = {
 
503
    {NULL,  NULL}   /* sentinel */
 
504
};
 
505
 
 
506
PyMODINIT_FUNC initmice_module(void) {
 
507
    if (PyType_Ready(&PyMiceModuleType) < 0)
 
508
        return;
 
509
 
 
510
    PyObject* module = Py_InitModule3
 
511
                           ("mice_module", _keywdarg_methods, module_docstring);
 
512
    if (module == NULL) return;
 
513
 
 
514
    PyTypeObject* mm_type = &PyMiceModuleType;
 
515
    Py_INCREF(mm_type);
 
516
    PyModule_AddObject
 
517
                   (module, "MiceModule", reinterpret_cast<PyObject*>(mm_type));
 
518
 
 
519
    // C API
 
520
    PyObject* mod_dict = PyModule_GetDict(module);
 
521
    PyObject* cem_c_api = PyCObject_FromVoidPtr(reinterpret_cast<void *>
 
522
                                            (C_API::create_empty_module), NULL);
 
523
    PyObject* gmm_c_api = PyCObject_FromVoidPtr(reinterpret_cast<void *>
 
524
                                                (C_API::get_mice_module), NULL);
 
525
    PyObject* smm_c_api = PyCObject_FromVoidPtr(reinterpret_cast<void *>
 
526
                                                (C_API::set_mice_module), NULL);
 
527
    PyDict_SetItemString(mod_dict, "C_API_CREATE_EMPTY_MODULE", cem_c_api);
 
528
    PyDict_SetItemString(mod_dict, "C_API_GET_MICE_MODULE", gmm_c_api);
 
529
    PyDict_SetItemString(mod_dict, "C_API_SET_MICE_MODULE", smm_c_api);
 
530
}
 
531
 
 
532
 
 
533
PyObject* C_API::create_empty_module() {
 
534
    return _alloc(&PyMiceModuleType, 0);
 
535
}
 
536
 
 
537
MiceModule* C_API::get_mice_module(PyObject* self) {
 
538
    if (self->ob_type != &PyMiceModuleType) {
 
539
        PyErr_SetString(PyExc_TypeError,
 
540
                        "Failed to resolve object as MiceModule");
 
541
        return NULL;
 
542
    }
 
543
    PyMiceModule* py_mod = reinterpret_cast<PyMiceModule*>(self);
 
544
    return py_mod->mod;
 
545
}
 
546
 
 
547
int C_API::set_mice_module(PyObject* self, MiceModule* mod) {
 
548
    if (self->ob_type != &PyMiceModuleType) {
 
549
        PyErr_SetString(PyExc_TypeError,
 
550
                        "Failed to resolve object as MiceModule");
 
551
        return 0;
 
552
    }
 
553
    PyMiceModule* py_mod = reinterpret_cast<PyMiceModule*>(self);
 
554
    if (py_mod->mod != NULL) {
 
555
        delete mod;
 
556
    }
 
557
    // I can't keep memory consistent if I allow access back up the tree.
 
558
    mod->setMother(NULL);
 
559
    py_mod->mod = mod;
 
560
    return 1;
 
561
}
 
562
}
 
563
}