ImportError: ... undefined symbol

1,080 views
Skip to first unread message

Daniel Woodhouse

unread,
Aug 24, 2010, 11:07:25 AM8/24/10
to cython-users
Hi,

I have developed a function in C using a library called flint (http://
www.flintlib.org/ I am actually using the unreleased flint2), and am
in the process of trying to wrap it using cython. I keep on running
into a particular error when I try to use some functions.

First here is the code in a file sineDemo.pxd (the name is because I
built it up from some example code that used math.h):



cdef extern from "stdlib.h":
ctypedef unsigned long size_t
void free(void *ptr)
void *malloc(size_t size)
void *realloc(void *ptr, size_t size)

cdef extern from "math.h":
double sin(double)

cdef extern from "../../flint2/fmpz.h":
ctypedef struct fmpz_t:
pass
void fmpz_init(fmpz_t f)
void fmpz_clear(fmpz_t f)
void fmpz_print(fmpz_t x)
void fmpz_neg(fmpz_t, fmpz_t)
#void fmpz_set_si(fmpz_t f, long val)
#char * fmpz_get_str(char * str, int b, fmpz_t f)



And here is the file sineDemo.pyx:

cimport sineDemo

def evalWithSine(array):
vect = []
for i in array:
vect.append(sineDemo.sin(<double>i))
return vect

def twoSine(x):
return sineDemo.sin(<double>x)

def call_fmpz_t():
cdef sineDemo.fmpz_t number

def set_fmpz_t():
cdef sineDemo.fmpz_t number
sineDemo.fmpz_init(number)
sineDemo.fmpz_clear(number)
sineDemo.fmpz_print(number)
sineDemo.fmpz_neg(number, number)
#cdef long num2 = <long>num
#sineDemo.fmpz_set_si(number, num2)
#cdef char * word
#word = sineDemo.fmpz_get_str(word, <int>10, number)


As you can hopefully see I have tried to import functions from a
header file fmpz.h. The function fmpz_init, fmpz_clear, fmpz_print all
work fine (and are inline c functions if that makes any difference),
so far as I can tell.
Trying to use fmpz_neg or fmpz_set_si or fmpz_get_str produces the
following king of error when I try and import sineDemo in python:


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: ./sineDemo.so: undefined symbol: fmpz_neg


Also here is what gets printed out when I run the setup script:

running build_ext
cythoning sineDemo.pyx to sineDemo.c
building 'sineDemo' extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -
Wstrict-prototypes -I/home/danielwoodhouse/flint2 -fPIC -I/usr/include/
python2.6 -c sineDemo.c -o build/temp.linux-x86_64-2.6/sineDemo.o
In file included from ../../flint2/fmpz.h:31,
from sineDemo.c:158:
../../flint2/nmod_vec.h: In function ‘_nmod_vec_copy’:
../../flint2/nmod_vec.h:160: warning: implicit declaration of function
‘mpn_copyi’
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -L/home/wbhart/
lib/:-L/home/danielwoodhouse/flint2/:-L/usr/local/lib/ -I/home/
danielwoodhouse/flint2 build/temp.linux-x86_64-2.6/sineDemo.o -lmpir -
o sineDemo.so


I don't think the warning about mpn_copyi has anything to do with the
error.

If anyone can tell me what I am doing wrong or give any helpful
suggestions, that would be fantastic. Please do ask further questions.

-Daniel
What is causeint

Robert Bradshaw

unread,
Aug 24, 2010, 11:16:58 AM8/24/10
to cython...@googlegroups.com

Why so? I see it does compile, but you're probably missing an #include
(cdef extern from) somewhere.

> If anyone can tell me what I am doing wrong or give any helpful
> suggestions, that would be fantastic. Please do ask further questions.

It looks like you're not linking against all the required libraries in
your setup.py.

- Robert

Daniel Woodhouse

unread,
Aug 25, 2010, 6:27:32 AM8/25/10
to cython-users
You were right. I managed to get it to work by getting the libraries
to link properly. Now that I've solved that problem I've run into a
stranger problem. Here is my new .pyx file:


cimport gps

def getPeriodSequence(coeffs, exponents, unsigned long monomial, pow,
primes):

cdef:
int power = pow
int l = len(exponents)
int lp = len(primes)

gps.fmpz_t *zeroCoeffs = <gps.fmpz_t *>gps.malloc(sizeof(gps.fmpz_t)
* power)
unsigned long * exps = <unsigned long *>gps.malloc(sizeof(unsigned
long) * l)
long *coef = <long *>gps.malloc(sizeof(unsigned long) * l)
unsigned long *p = <unsigned long *>gps.malloc(sizeof(unsigned long)
* lp)

for i in range(0, l):
exps[i] = exponents[i]
coef[i] = coeffs[i]
for i in range(0, lp):
p[i] = primes[i]

gps.get_period_sequence(zeroCoeffs, coef, exps, l, monomial, power,
p, lp)

vect = []
cdef char * word
for i in range(0, power):
word = gps.fmpz_get_str(word, <int>10, zeroCoeffs[i])
py_str = word
vect.append(int(py_str))

gps.free(zeroCoeffs)
gps.free(exps)
gps.free(coef)
gps.free(p)

return vect


This function works fine unless you call it twice in a row with
exactly the same arguements and then you get the following error:
"Fatal Python error: GC object already tracked", or in some cases a
segmentation error. Any kind of explanation as to what this means
would be very welcome.

-Daniel

Robert Bradshaw

unread,
Aug 25, 2010, 12:52:15 PM8/25/10
to cython...@googlegroups.com

Very strange. Any chance you can whittle this down to a smaller
example that doesn't require any external libraries?

- Robert

Daniel Woodhouse

unread,
Aug 27, 2010, 11:38:16 AM8/27/10
to cython...@googlegroups.com
Managed to solve the problem.

The line  "word = gps.fmpz_get_str(word, <int>10, zeroCoeffs[i])" needed to use two different string variables. One to be given as an arguement, and another to take the returned value.

-Daniel
Reply all
Reply to author
Forward
0 new messages