Python extension modules
MarkH at ActiveState.com
Thu Nov 1 12:31:17 CET 2001
[posted and mailed]
> I need Python objects to contain and "represent" native C
> structs. Is there a way to do this *without* defining a new
Check out the struct module. It allows you to pack and unpack "blobs"
of data (usually in a string), given a format string.
So one approach would be to define a Python class in a .py file, that
wraps up the struct module.
def __init__(self, int1=0, int2=0):
def __getattr__(self, attr):
return struct.pack("ii", self.int1, self.int2)
raise AttributeError, "%r.%s" % (self, attr)
print "Data is", repr(f._value_)
Yields: Data is '\xff\x00\x00\x00\x01\x00\x00\x00'
Your extension module could create instances of this class to return to
callers. Something like:
(error checking omitted, but _do_ add it :)
PyObject *mod = PyImport_ImportModule("foo");
PyObject *cls = PyObject_GetAttrString(mod, "Foo");
PyObject *args = Py_BuildValue(cs.int1, cs.int2);
PyObject *instance = PyEval_CallObject(cls, args);
// instance is a new object ready to return, with a new reference
It could accept class instances as params - use something like:
PyObject *inst, *str;
if (!PyString_Check(str)) ...
if (PyString_Length(str)!= sizeof(cs)) // eek...
memcpy(&cs, PyString_AsString(str), sizeof(cs));
The other alternative, as you discovered, is what you outline below:
> Question about defining a new type, then. Functions
> (package-scoped functions not tied to a class) are declared
> via the PyMethodDef array, right? So, this is where an
> instance constructor might go?
[snip lots of stuff that looked correct, but I really didn't look too hard]
> static PyObject*
> MyNew_getattr(MyNew *self, char *name)
You should use Python declarations exactly - use "PyObject" instead of
"MyNew". MyNew may fail in some C++ scenarios.
> return Py_FindMethod(MyNew_methods, (PyObject *)self, name);
> So, now you can: "rv = instance.method()"
Yep. You can also add simple checks to getattr to make it look more
like a struct:
MyNew_getattr(PyObject *self, char *name)
if (strcmp(name, "int1")==0)
return PyInt_FromLong( ((MyNew *)self)->pcs->int1);
else if ...
// try methods last.
return Py_FindMethod(MyNew_methods, (PyObject *)self, name);
> Is this (use of "getattr" method, which calls Py_FindMethod)
> the accepted convention?
> Am I on the right track? Thanks in advance...
> P.S. There is perhaps a train-of-thought missing from the
> Extending tutorial that I lost hair figuring out this
> morning. I would be more than happy to offer possible
> improvements, if there is interest...
Sure is! If submit patches to the documentation to the source-forge
patch manager, you would be loved by many :)
More information about the Python-list