On 10 May 2012 17:39, Stefan Behnel python_capi@behnel.de wrote:
Mateusz Loskot, 10.05.2012 18:17:
On 10 May 2012 14:55, Mateusz Loskot wrote:
On 10 May 2012 14:01, Stefan Behnel wrote:
You can execute any Python code from your C code. Look for the PyRun_*() functions.
Do you mean something similar to this approach?
/* dynamically generated lengthy class definition */ const char* c = "class A(object): pass";
PyObject* class_a = PyRun_StringFlags(c, ...); PyObject_SetAttrString(module, "A", class_a)
The pseudo-code above is incorrect. I have come up with the following example of dynamically generating new Python class, indirectly through script using class keyword. Such dynamically created class is added to module dictionary:
/* error checks removed for brevity */
static PyModuleDef embmodule = { ... };
PyInit_emb(void) { PyObject* m = PyModule_Create(&embmodule); PyObject* d = PyModule_GetDict(m);
/* Required to allow 'class' use in context of module which is not yet complete and ready. Otherwise, error is thrown: ImportError: __build_class__ not found */ PyObject* builtins = PyEval_GetBuiltins(); PyDict_SetItemString(d, "__builtins__", builtins);
/* Python class is dynamically generated */ const char* c = "class A(object):\n\tpass"; /* sample class */
/* Create object for A class, automatically added to the module dictionary as emb.A */ PyRun_StringFlags(c, Py_file_input, d, d, NULL);
You want to take the result here, if only to decref it.
Right, I missed it out from the example.
What you'd do next is to initialise your types in the module (or let CPython do it for you through the inittab)
I'm not sure I completely understand it. I assume that executing these two lines, in context of the module:
const char* c = "class A(object):\n\tpass"; PyRun_StringFlags(c, Py_file_input, d, d, NULL);
creates complete and initialised A class within this module. Doesn't it?
and then let the Python classes inherit from them, stick C methods into them, etc.
Right.
Thanks for the patience :)
This approach works well. If anyone noticed a problem or there is better way to do the same, please let me know.
Looks ok to me.
Great!
Here's the equivalent code in Cython:
class A(object): pass
(except that it executes faster because it doesn't run through the Python parser and interpreter at runtime, but I don't think that matters much at module init time).
It looks really helpful and simple, I'll remember, and chances are I will use it in next project.
Best regards,
Mateusz Loskot, http://mateusz.loskot.net