[capi-sig] Creating type object dynamically in run-time

Campbell Barton ideasman42 at gmail.com
Thu May 10 18:38:31 CEST 2012


If speed of class creation is important (as it is for us). suggest to
call type directly rather then evaluating a string every time and
executing it - this is one way.


		/* always use O not N when calling, N causes refcount errors */
		newclass = PyObject_CallFunction((PyObject *)&PyType_Type, (char
*)"s(O) {sss()}",
		                                 idname, py_base_class,
"__module__", "bpy.types", "__slots__");

which is like doing this in python...

  type(idname, (py_base_class, ), dict(__module__="bpy.types", __slots__=()))



On Thu, May 10, 2012 at 6:17 PM, Mateusz Loskot <mateusz at loskot.net> wrote:
> On 10 May 2012 14:55, Mateusz Loskot <mateusz at loskot.net> wrote:
>> On 10 May 2012 14:01, Stefan Behnel <python_capi at behnel.de> 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 noddy.A */
>    PyRun_StringFlags(c, Py_file_input, d, d, NULL);
>
>    return m;
> }
>
> This approach works well.
> If anyone noticed a problem or there is better way to do the same,
> please let me know.
>
> Best regards,
> --
> Mateusz Loskot, http://mateusz.loskot.net
> _______________________________________________
> capi-sig mailing list
> capi-sig at python.org
> http://mail.python.org/mailman/listinfo/capi-sig



-- 
- Campbell


More information about the capi-sig mailing list