problems with compiling and loading C++ extension
Dear People,
I have been having an odd problem with compiling and loading a simple
C++ extension to python (as a .so file in Linux). Unfortunately, I'll
need to include my files in here so I apologize in advance for the
length of this message.
You can download also the files below from
http://www.stat.unc.edu/students/faheem/python/python.tar.gz in case
that is more convenient.
This needs blitz++ and python's distutils and numarray to compile.
When I try to load arrmod.so into python I get
In [1]: import arrmod
---------------------------------------------------------------------------
ImportError Traceback (most recent call
last)
/tmp/wc/corrmodel/ex/<console>
ImportError: ./arrmod.so: undefined symbol:
_Z11py_to_blitzIdLi2EEN5blitz5ArrayIT_XT0_EEEP13PyArrayObject
If I move the py_to_blitz routine from conv.cc back into arrmod.cc,
the error disappears, arrmod loads in python, and everything works
correctly. I'm not sure what is going on here. Can someone enlighten
me? At first I thought it might have to do with the need for C
linkage, but I tried that, and it does not appear to be the case.
I also got the following compilation warning, which I don't
understand. I don't know if that is relevant.
---------------------------------------------------------------------
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -O3 -Wall
-Wstrict-prototypes -fPIC -I/usr/include/python2.3 -c conv.cc -o
/tmp/temp.linux-i686-2.3/conv.o -Wall
/usr/include/python2.3/Numeric/arrayobject.h:286: warning:
`void**PyArray_API'
defined but not used
---------------------------------------------------------------------
Thanks in advance for any enlightenment.
Faheem.
**********************************************************************
Makefile
**********************************************************************
arrmod.so: arrmod.cc common.hh conv.cc
python setup.py build --build-base=/tmp --build-lib=.
# may not do the right thing for everyone
clean:
rm arrmod.so
rm -r /tmp/temp.linux-i686-2.3
**********************************************************************
**********************************************************************
setup.py
**********************************************************************
from distutils.core import setup, Extension
module4 = Extension('arrmod',
sources = ['arrmod.cc','conv.cc'],libraries=["blitz","m"],
extra_compile_args = ['-Wall'])
setup (name = 'arrmod',
version = '1.0',
description = 'This module performs different operations on arrays',
ext_modules = [module4]
)
**********************************************************************
**********************************************************************
common.hh
**********************************************************************
#include "Python.h"
#include "Numeric/arrayobject.h"
#include
Faheem Mitha wrote:
Dear People,
I have been having an odd problem with compiling and loading a simple C++ extension to python (as a .so file in Linux). Unfortunately, I'll need to include my files in here so I apologize in advance for the length of this message.
Are you sure you have all the needed 'extern C' declarations in place? Remember, you'll be compiling this thing with a C++ compiler, but it will be called by Python's C runtime. Hence, _all_ python-visible functions will need to be wrapped in extern C calls, including your module initializer (you often don't think of this one, because it's implicitly Here's a typical snippet for a python-visible function in one of my C++ blitz-based extensions: // mts_contract extern "C" { static PyObject* mts_contract(PyObject *self, PyObject *args) { PyArrayObject *M_array, *T_array; ... and here's what the module initializer looks like: /* Module initializer -- called on first import. It *must* be called initMODULENAME */ extern "C" void initutils_() { import_array(); // Initialize the dimension dispatch tables init_mts_contract_funcs(); init_mtt_contract2_funcs(); init_mseqtt_contract2_funcs(); // Create the module and add the functions PyObject* mod = Py_InitModule4("utils_", compiled_methods, module_doc, (PyObject*)NULL, PYTHON_API_VERSION); // Add some symbolic constants to the module PyObject* mod_dict = PyModule_GetDict(mod); // Make a module-level exception // The first argument is what the exception class will appear to be // in python. The return value is a class object. utils_Error = PyErr_NewException("utils_.utils_Error", NULL, NULL); // Add it to the module's dictionary. Second argument is the key PyDict_SetItemString(mod_dict, "utils_Error", utils_Error); // Add other constants here PyDict_SetItemString(mod_dict, "__all__", Py_BuildValue("sss", "mts_contract2", "mtt_contract2", "mseqtt_contract2" )); // Check for errors if (PyErr_Occurred()) Py_FatalError("can't initialize module utils_"); } I hope this helps you. Mail me if you want the full files (this is old code I don't use anymore, so it may not quite compile now anymore, but you can still look a it). Cheers, f
On Wed, 7 Apr 2004, Fernando Perez wrote:
I hope this helps you. Mail me if you want the full files (this is old code I don't use anymore, so it may not quite compile now anymore, but you can still look a it).
Yes, please do send me your files (preferably as a tar.gz). Thanks for the info. I expect you are right. I'll take a more careful look. One problem is that I don't understand the logic behind C linkage very well. For example, does it suffice to wrap the declaration of the function or do I need to wrap the definition too? Can you suggest a good reference, preferably online? My C++ books are not much help with this. Thanks. Faheem.
participants (2)
-
Faheem Mitha
-
Fernando Perez