Hello!
I'm quite new to Python and definitely a beginner in implementing Python extensions in C/C++. I've followed the structure given in the formal Python documentation to write the following code block:
//cmatmod.c
#include
static unsigned int eigenvect_calc(double *min_eps) { return 5; }
static PyObject *cmat_eigv(PyObject *self, PyObject *args) { double *min_eps; unsigned int m; if(!PyArg_ParseTuple(args, "d", &min_eps)) return NULL; m=eigenvect_calc(min_eps); return Py_BuildValue("I", m); } static PyMethodDef cmat_methods[]= { { "eigenvect", cmat_eigv, METH_VARARGS, "Comment"},{NULL, NULL, 0, NULL} };
void initcmat(void) { (void) Py_InitModule("cmat", cmat_methods); }
===========
I have succeeded to build and install this extension using disutils package in the setup.py file below:
from distutils.core import setup from distutils.extension import Extension setup(name='eigenvect', version='1.0', ext_modules=[Extension('cmat', ['cmatmod.c'])], )
========== But when I try to call eigenvect(3.0) from Python I would receive a core dump:
6 [main] python 2336 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped)
========== My question is what is wrong with the extension code above? Is it something with reference counting? I don't know which method is suitable for debugging extension codes. I've tried gdb but I didn't understand the debug information:
(gdb) >>> eigenvect(4.0)
Program received signal SIGSEGV, Segmentation fault. ---Type to continue, or q to quit--- 0x6abb248e in libpython2!PyEval_EvalFrameEx () from /usr/bin/libpython2.5dll (gdb)
========== /best regards
Gå in och titta på nätets roligaste filmer just nu eller ladda upp ditt eget bidrag på Spray Crazy. http://crazy.spray.se/
I'm not 100% sure, but try the following:
static unsigned int eigenvect_calc(double *min_eps) { return 5; }
static PyObject *cmat_eigv(PyObject *self, PyObject *args) {
Try adding a 3rd arg - PyObject *kw - although I was under the impression this should not matter, it might. Indeed, I hope it does, as I can't spot any other issue.
Mark
I suspect the problem is the following:
double *min_eps;
if (!PyArg_ParseTuple(args, "d", &min_eps)) return NULL;
That should be
double min_eps;
as Python is expecting a double, not a pointer to a double! And since the difference is about 4 bytes, that would explain the segfault. :-)
Anthony
On 8/14/07, Ali Alhakim <alika@spray.se> wrote:
Hello!
I'm quite new to Python and definitely a beginner in implementing Python extensions in C/C++. I've followed the structure given in the formal Python documentation to write the following code block:
//cmatmod.c
#include
static unsigned int eigenvect_calc(double *min_eps) { return 5; }
static PyObject *cmat_eigv(PyObject *self, PyObject *args) { double *min_eps; unsigned int m; if(!PyArg_ParseTuple(args, "d", &min_eps)) return NULL; m=eigenvect_calc(min_eps); return Py_BuildValue("I", m); } static PyMethodDef cmat_methods[]= { { "eigenvect", cmat_eigv, METH_VARARGS, "Comment"},{NULL, NULL, 0, NULL} };
void initcmat(void) { (void) Py_InitModule("cmat", cmat_methods); }
===========
I have succeeded to build and install this extension using disutils package in the setup.py file below:
from distutils.core import setup from distutils.extension import Extension setup(name='eigenvect', version='1.0', ext_modules=[Extension('cmat', ['cmatmod.c'])], )
========== But when I try to call eigenvect(3.0) from Python I would receive a core dump:
6 [main] python 2336 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped)
========== My question is what is wrong with the extension code above? Is it something with reference counting? I don't know which method is suitable for debugging extension codes. I've tried gdb but I didn't understand the debug information:
(gdb) >>> eigenvect(4.0)
Program received signal SIGSEGV, Segmentation fault. ---Type to continue, or q to quit--- 0x6abb248e in libpython2!PyEval_EvalFrameEx () from /usr/bin/libpython2.5dll (gdb)
========== /best regards
Gå in och titta på nätets roligaste filmer just nu eller ladda upp ditt eget bidrag på Spray Crazy. http://crazy.spray.se/
capi-sig mailing list capi-sig@python.org http://mail.python.org/mailman/listinfo/capi-sig
Hi, as mentioned before, the pointers the issue here,
Some other things you might want to consider. there more of a style thing ;)
static PyObject *cmat_eigv(PyObject *self, PyObject *value) { double min_eps = PyFloat_AsDouble(value); if (min_eps==-1 && PyErr_Occurred()) return NULL; return PyInt_FromLong((long)eigenvect_calc(min_eps)); } static PyMethodDef cmat_methods[]= { { "eigenvect", cmat_eigv, METH_O, "Comment"},{NULL, NULL, 0, NULL} };
notice that Iv replaced METH_VARARGS with METH_O, this means the function only accepts 1 arg and you can use that as a float without using PyArg_ParseTuple - This should be a bit faster too.
PyFloat_AsDouble will convert from ints or other non float types that support the PyNumber protocol.
I can see why this isnt used for an example because its much less generic.
Ali Alhakim wrote:
Hello!
I'm quite new to Python and definitely a beginner in implementing Python extensions in C/C++. I've followed the structure given in the formal Python documentation to write the following code block:
//cmatmod.c
#include
static unsigned int eigenvect_calc(double *min_eps) { return 5; }
static PyObject *cmat_eigv(PyObject *self, PyObject *args) { double *min_eps; unsigned int m; if(!PyArg_ParseTuple(args, "d", &min_eps)) return NULL; m=eigenvect_calc(min_eps); return Py_BuildValue("I", m); } static PyMethodDef cmat_methods[]= { { "eigenvect", cmat_eigv, METH_VARARGS, "Comment"},{NULL, NULL, 0, NULL} };
void initcmat(void) { (void) Py_InitModule("cmat", cmat_methods); }
===========
I have succeeded to build and install this extension using disutils package in the setup.py file below:
from distutils.core import setup from distutils.extension import Extension setup(name='eigenvect', version='1.0', ext_modules=[Extension('cmat', ['cmatmod.c'])], )
========== But when I try to call eigenvect(3.0) from Python I would receive a core dump:
6 [main] python 2336 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped)
========== My question is what is wrong with the extension code above? Is it something with reference counting? I don't know which method is suitable for debugging extension codes. I've tried gdb but I didn't understand the debug information:
(gdb) >>> eigenvect(4.0)
Program received signal SIGSEGV, Segmentation fault. ---Type to continue, or q to quit--- 0x6abb248e in libpython2!PyEval_EvalFrameEx () from /usr/bin/libpython2.5dll (gdb)
========== /best regards
Gå in och titta på nätets roligaste filmer just nu eller ladda upp ditt eget bidrag på Spray Crazy. http://crazy.spray.se/
capi-sig mailing list capi-sig@python.org http://mail.python.org/mailman/listinfo/capi-sig
-- Campbell J Barton (ideasman42)
Ali Alhakim wrote:
I'm quite new to Python and definitely a beginner in implementing Python extensions in C/C++.
You might want to take a look at Pyrex or Cython. Both allow you to write C extensions in a very Python-like language. Both use the same language, but the C code that Cython generates is a lot more efficient.
http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ http://www.cython.org/
Stefan
Hi, I need to assign a value to a function (PyCFunction) from the C apy
The python equivalent is...
def foo(): pass foo.Value = 10
Iv looked a fair bit in python source code and cant see how this is possible...
The PyCFunction struct looks like this...
typedef struct { PyObject_HEAD PyMethodDef *m_ml; /* Description of the C function to call */ PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ PyObject *m_module; /* The __module__ attribute, can be anything */ } PyCFunctionObject;
m_ml cant be used, m_module looks like its for internal use only, so if this is possible in C, its peobably stored in *m_self,
Anyone know a solution for this?
- Cam
Campbell Barton <cbarton@metavr.com> writes:
Iv looked a fair bit in python source code and cant see how this is possible...
The thing is, a Python-defined function isn't stored in a PyCFunction, it's stored in the PyFunction object, which includes a func_dict member.
I'm afraid you won't be able to easily assign values to a PyCFunction. You can try to inherit PyCFunction and add a dict to it, or you can create your own callable type that has a dict.
participants (6)
-
Ali Alhakim
-
Anthony Tuininga
-
Campbell Barton
-
Hrvoje Niksic
-
Mark Hammond
-
Stefan Behnel