views:

138

answers:

2

OK, I've beaten my head against this problem for a while now, it's time to ask for help.

I'm writing some libraries in C, for to be called from Python via ctypes.

I've done this sucessfully with one library, but this library only very vanilla dependancy, namely (fstream, math, malloc, stdio, stdlib).

Now the other library I'm working on has more complicated dependencies. For example, I'll try to use fftw3.

I'll just try to compile a simple cpp file containing

int foo()
{
    void *p  = fftw_malloc( sizeof(fftw_complex)*64 );
    fftw_free(p);

    printf("foo called.\n");

    return 0;
}        

as a test.

I compile it as

icpc -Wall -fPIC -c waveprop.cpp -o libwaveprop.o $std_link
icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o 

cp waveprop.so.1.0 /usr/local/lib/
rm waveprop.so.1.0
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so.1

all works. Now I try test it with another cpp file containing 

int main()
{
    foo();
}

result:

icpc test.cpp -lwaveprop 
/lib/../lib64/libwaveprop.so: undefined reference to `fftw_free'
/lib/../lib64/libwaveprop.so: undefined reference to `fftw_malloc'

Which is entirely reasonalbe. next:

icpc test.cpp -lwaveprop -lfftw3
./a.out
foo called.

great. But now when I try to load the library with ctypes:

>>> from ctypes import *
>>> print cdll.LoadLibrary('/usr/local/lib/libwaveprop.so.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/ctypes/__init__.py", line 431, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib64/python2.6/ctypes/__init__.py", line 353, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: /usr/local/lib/libwaveprop.so.1: undefined symbol: fftw_free

So it's the same problem, but I have no idea how to resolve it for ctypes. I've tried various things without any success, and I'm pretty stuck at this point; googling hasn't really helped. Thanks in advance for any help.

-nick

A: 

You need to link libwaveprop.so itself against the fftw3 library. Otherwise Python simply won't know where to go to get those missing symbols; mind-reading isn't implemented in any programming language.

Donal Fellows
Thanks for the reply.That's one of the things I tried. icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o -lfftw3and icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o both give the same error: ld: /usr/local/lib/libfftw3.a(malloc.o): relocation R_X86_64_PC32 against symbol `fftw_kernel_malloc' can not be used when making a shared object; recompile with -fPIC ld: final link failed: Bad valueI'm not sure what to do with that. Any ideas?thanks,-nick
nmaxwell
Well, “compile to `.o` with `-fPIC` and link to `.so` against the libraries that you depend on” is the technique that I've learned. Can't diagnose what's wrong without further info, sorry.
Donal Fellows
+1  A: 

OK, thanks for your help.

to get this to work I had to include the dependencies when linking (duh). I had tried this before but got an error, so solve this I had to recompile fftw with '-fpic' as a CPP flag. all works now.

icpc -Wall -fPIC -c waveprop.cpp -o libwaveprop.o $std_link
icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o -lfftw3

cp waveprop.so.1.0 /usr/local/lib/
rm waveprop.so.1.0
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so.1

thanks, -nick

nmaxwell