Defining Python class methods in C
Bryan
belred1 at yahoo.com
Sat Mar 22 18:44:58 EST 2003
thanks alex for your help so far. i'm very close to getting this
working the way i want to. but i'm still having trouble getting the
callback from the python script to the c code to work. there must be
some fundamental part i'm not understanding. here is the c code that
instatiates a Context class and setting a context value in __init__.
this part is now working. after the Context object is created, it's
passed to start. start is successfully called and can see that the
parameter being passed in is a Context instance. what's not working
is the callback into the Context class.
here is the c-code creating context.Context and calling start:
PyImport_AppendInittab("context", initcontext);
Py_Initialize();
/* create a context object */
py_mod_context = PyImport_ImportModule("context");
if (!py_mod_context) goto clean_exit;
py_cls_Context = PyObject_GetAttrString(py_mod_context, "Context");
if (!py_cls_Context) goto clean_exit;
sprintf(addr, "%p", ctx);
py_tuple_addr = Py_BuildValue("(s)", addr);
if (!py_tuple_addr) goto clean_exit;
py_obj_Context = PyObject_CallObject(py_cls_Context, py_tuple_addr);
if (!py_obj_Context) goto clean_exit;
/* call start */
py_call_start = PyObject_GetAttrString(py_mod_provider, "start");
if (py_call_start && PyCallable_Check(py_call_start)) {
PyObject_CallFunctionObjArgs(py_call_start, py_obj_Context,
NULL);
}
here's the python script that's being called. i am not importing the
context module in the script. this is an intentional part of the
design. but maybe i really do need to import the context module.
def start(ctx):
print 'context', ctx
print 'doc', ctx.__doc__, 'end doc'
print 'path', ctx.get_path(), 'end path'
here is the output from start. notice the ?, no doc string, no path
string including the 'end path' string. i'm assuming get_path wasn't
found and an attribute exception occured. also, my breakpoint never
stopped in the get_path callback method. why does python show a ?.
why doesn't it know that it's from the context module?
context <?.Context instance at 0x00AE7D08>
doc None end doc
path
here is the Context object:
#include <python/Python.h>
staticforward PyTypeObject context_type;
typedef struct {
PyObject_HEAD
char context[64];
} context_object;
static PyObject* context_init(PyObject *self, PyObject *args)
{
context_object *context_obj;
PyObject *type;
char *s = NULL;
if (!PyArg_ParseTuple(args, "Os", &type, &s)) return NULL;
context_obj = PyObject_New(context_object, &context_type);
strncpy(context_obj->context, s, sizeof(context_obj->context));
context_obj->context[sizeof(context_obj->context)-1] = '\0';
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* context_get_path(PyObject *self, PyObject *args)
{
context_object *context_obj = (context_object*)self;
PyObject *py_str_path = NULL;
if (context_obj) {
/* not a real path yet,
just pass back the string internal context string */
py_str_path = PyString_FromString(context_obj->context);
}
if (py_str_path) {
return py_str_path;
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
static void context_dealloc(PyObject *self)
{
PyObject_Del(self);
}
static PyTypeObject context_type = {
PyObject_HEAD_INIT(NULL)
0,
"Context",
sizeof(context_object),
0,
context_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0 /* tp_hash */
};
static PyMethodDef context_methods[] = {
{"__init__", context_init, METH_VARARGS, "Create a new context
object."},
{"get_path", context_get_path, METH_NOARGS, "Get the path"},
{NULL, NULL, 0, NULL}
};
static PyMethodDef module_methods[] = { {NULL, NULL, 0, NULL } };
void initcontext(void)
{
PyMethodDef *def;
/* create a context object */
PyObject *module = Py_InitModule("context", module_methods);
PyObject *module_dict = PyModule_GetDict(module);
PyObject *class_dict = PyDict_New();
PyObject *class_name = PyString_FromString("Context");
PyObject *class_obj = PyClass_New(NULL, class_dict, class_name);
PyDict_SetItemString(module_dict, "Context", class_obj);
Py_DECREF(class_dict);
Py_DECREF(class_name);
Py_DECREF(class_obj);
/* add methods to class */
for (def = context_methods; def->ml_name != NULL; def++) {
PyObject *func = PyCFunction_New(def, NULL);
PyObject *method = PyMethod_New(func, NULL, class_obj);
PyDict_SetItemString(class_dict, def->ml_name, method);
Py_DECREF(func);
Py_DECREF(method);
}
context_type.ob_type = &PyType_Type;
}
thanks,
bryan
More information about the Python-list
mailing list