keeping local state in an C extension module

2011-06-30 Thread Daniel Franke
Hi all.

For a project I implemented a extension module in C. Given the
excellent documentation everything was straightforward and works fine
so far.

Up until now I kept local state in global static variables, but would
like to change this to pass a pointer to a state structure around. The
Py_InitModule4() [1] function seems to allow this by giving the user
the option to specify the 'self' object passed to the module's
functions. In this case, the 'self' argument should be a raw C pointer
malloc'ed elsewhere that should be rolled into a PyObject and be made
accessible later in the extension functions. Example code:

static PyObject* module_func(PyObject *self, PyObject *args) {
  state_t *state = (state_t*) PyRawPointerFromPyObject(self);
  /* use state */
  Py_RETURN_NONE;
}

static PyMethodDef bms_methods[] = {
  { "func", module_func, METH_VARARGS, "" },
  { NULL, NULL, NULL, NULL }
};

void my_module_init(state_t *state) {
  Py_InitModule4("_mymodule", module_methods,
 "My Extension Module",
 PyObjectFromRawPointer(state),
 PYTHON_API_VERSION);
}

Here, of course, the functions PyObjectFromRawPointer(void*) and void*
PyRawPointerFromPyObject(PyObject*) are missing. Is there anything
like this in the Python C-API? If not, how could it be implemented? Or
is this approach a stupid idea to begin with? Pointers would be highly
appreciated.

Thanks

   Daniel


[1] 
http://docs.python.org/c-api/allocation.html?highlight=py_initmodule4#Py_InitModule4
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: keeping local state in an C extension module

2011-06-30 Thread Daniel Franke
Hi Stefan.

2011/6/30 Stefan Behnel :
> Don't miss out taking a look at Cython, just in case it's going to be a
> non-trivial project.

I think this work still qualifies as trivial enough in this regard.
But thanks for the hint!


> There's a PEP for Py3 that enables this through a general framework. In
> general, to achieve this, you may want to allocate the module content
> (including types etc.) on the heap rather than statically.
>
> http://www.python.org/dev/peps/pep-3121/

Perfect! Unfortunately, it seems not to be available in 2.x, so
unusable for now. For the foreseeable future the project can not
depend on 3.x as many (internal) target systems are "stable", i.e. are
not updated besides security stuff.


> Take a look at PyCapsule, it may (or may not) be enough for your use case.

Also a perfectly good solution - unfortunately the same comment about
3.0 applies here.


> However, note the comment about Py_InitModule4() in the docs, where it says
> that the 'self' passing feature isn't used very often. You may or may not
> want to (or need to) use it.

If there are too many hoops to jump through to get a reasonable
solution working for 2.[567], I might as well go back to
Py_InitModule() and static variables. It's somewhat ugly, but it
works.

Thanks for the info!

 Daniel
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: keeping local state in an C extension module

2011-06-30 Thread Daniel Franke
2011/6/30 Stefan Behnel :
>> If there are too many hoops to jump through to get a reasonable
>> solution working for 2.[567], I might as well go back to
>> Py_InitModule() and static variables. It's somewhat ugly, but it
>> works.
>
> Py2.x has a PyCObject, basically the predecessor to PyCapsule. Writing your
> own little type is another option.

For reference: PyCObject has PyCObject_FromVoidPtr() and
PyCObject_AsVoidPtr() -- exactly what I was looking for (no idea why I
missed it for so long?!). Ok, and it also has the note: "The CObject
API is deprecated as of Python 2.7. Please switch to the new Capsules
API." which is of no concern here :)

Thanks heaps!

 Daniel
-- 
http://mail.python.org/mailman/listinfo/python-list


defining class and subclass in C

2012-01-14 Thread Daniel Franke

Hi all.

I spent some days and nights on this already and my google-fu is running out.

I'd like to implement the equivalent of this Python code in a C-extension:

>>> class A(object):
...  pass
>>> class B(A):
...  pass
>>> A

>>> B

>>> B.__bases__
(,)

However, loading my C-code (quoted below) I get:

>>> import ca
>>> ca

>>> ca.ca


Here I'd expect "" instead?! And I never managed a proper 
subclass :|

The point of the excercise: with "ca" and "cb" properly implemented, I'd like 
to subclass "cb" not from "ca", but from the Python "class A" - if possible?!

Could somepne kindly point out my mistake(s) and set me back on track?

Thanks

Daniel

--
#include 

typedef struct {
  PyObject_HEAD
} ca;

static PyTypeObject ca_Type = {
  PyObject_HEAD_INIT(NULL)
};

PyMODINIT_FUNC initca(void) {
  PyObject *ca;

  ca_Type.tp_name  = "ca.ca";
  ca_Type.tp_basicsize = sizeof(ca);
  ca_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;

  if (PyType_Ready(&ca_Type) < 0)
return;

  ca = Py_InitModule3("ca", NULL, "ca module");
  if (ca == NULL)
return;

  Py_INCREF(&ca_Type);
  PyModule_AddObject(ca, "ca", (PyObject*)&ca_Type);
}

$ gcc -Wall -Wextra -g -fPIC -I/usr/include/python2.7 ca.c \
  -shared -Wl,-soname,ca.so -o ca.so -lpython2.7

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: defining class and subclass in C

2012-01-14 Thread Daniel Franke
On Saturday 14 January 2012 22:15:36 Daniel Franke wrote:
> Here I'd expect "" instead?! And I never managed a proper
> subclass :|

Found an explanation on type/class at [1]: "he difference between the two is 
whether the C-level type instance structure is flagged as having been 
allocated on the heap or not" - hu?

With this info, I went ahead and tried the code quoted below. Now I get:

>>> import cmod
>>> cmod.ca

>>> cmod.cb

>>> cmod.ca.__bases__
(,)
>>> cmod.cb.__bases__
(,)

which seems to make sense besides the "type" instead of "class"?!

What threw me is that I expected that I'd need to explicitly subclass the 
"object" type, from which I assumed for some reason I'd also inherit the 
.tp_new member. This is obviously not the case.

Now the last question is, how do I get the a_type of Python class to use it as 
base for "cb"?

On lives and learns.

Daniel


[1] http://utcc.utoronto.ca/~cks/space/blog/python/ClassesAndTypes

--
#include 

typedef struct {
  PyObject_HEAD
} ca;

static PyTypeObject ca_Type = {
  PyObject_HEAD_INIT(NULL)
};


typedef struct {
  PyObject_HEAD
} cb;

static PyTypeObject cb_Type = {
  PyObject_HEAD_INIT(NULL)
};


PyMODINIT_FUNC initcmod(void) {
  PyObject *cmod;

  ca_Type.tp_name  = "cmod.ca";
  ca_Type.tp_basicsize = sizeof(ca);
  ca_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  ca_Type.tp_new   = PyType_GenericNew;
  ca_Type.tp_base  = &PyBaseObject_Type;

  if (PyType_Ready(&ca_Type) < 0)
return;

  cb_Type.tp_name  = "cmod.cb";
  cb_Type.tp_basicsize = sizeof(cb);
  cb_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  cb_Type.tp_base  = &ca_Type;

  if (PyType_Ready(&cb_Type) < 0)
return;

  cmod = Py_InitModule3("cmod", NULL, "c module");
  if (cmod == NULL)
return;

  Py_INCREF(&ca_Type);
  PyModule_AddObject(cmod, "ca", (PyObject*)&ca_Type);

  Py_INCREF(&cb_Type);
  PyModule_AddObject(cmod, "cb", (PyObject*)&cb_Type);
}

-- 
http://mail.python.org/mailman/listinfo/python-list


building foo.pyd, _initfoo vs. initfoo

2012-01-22 Thread Daniel Franke

Hi all.

Usually I work on Linux and all my cmake-built Python extensions working there 
without trouble. Now these things need to work on Windows as well. While the 
code itself compiles fine, linking and loading makes trouble.

First of, to successfully link everything with mingw (g++-4.4.0, somewhat 
oldish) I had to define:

-DPy_ENABLE_SHARED -DPy_BUILD_CORE

Not sure if this makes sense, but if it works, fine by me. Now, loading the 
module is different. 

First attempts of loading the module failed miserably until I found out that 
Python expects files with a .pyd suffix. Very innovative to throw off the 
layman. Took that hurdle.

Finally, on load of foo.pyd, I get:

"Import Error: dynamic module does not define init function (initfoo)"

As this module loads fine in Linux, there is an initfoo() defined. Checking 
with `nm`, I find two things:

 1. The function name is mangled (__Z12initfoov)
 -> the module is compiled with g++, but I believed that PyMODINIT_FUNC
includes the 'extern "C"' apparatus?

 2. Manually enclosing the init function with 'extern "C" {}" still yields the
same error
 -> the function name also comes with a leading underscore '_', i.e.
"_initfoo", not "initfoo"

Could someone knowledge with Windows and MinGW help me to sort this out? Tools 
used: cmake-2.8.3, mingw-? with gcc-4.4 and Python-2.7.2 from python.org.

Thanks

Daniel

-- 
http://mail.python.org/mailman/listinfo/python-list