简体   繁体   中英

undefined symbol: PyArray_API when using numpy and swig

I am trying to wrap in Python some code written in C with Swig. The purpose is to create numpy arrays in Python and use them in C as a pointer to doubles.

Here is the code:

In Swig:

%apply (int DIM1, double* INPLACE_ARRAY1) {(int n, double* x)} extern void f(int n, double* x);

In C:

void f(int n, double* x)

Unfortunately when I try to load the module, I obtain the following error message:

ImportError: _test.so: undefined symbol: PyArray_API

Thanks!

We'll need some more details as to how you build/link this. Based on the available information, my best guess is that since SWIG does not support C (I know there's a fork), but your other code is, you linked the final module library with the C compiler instead of the C++ one.

Here's a basic working example to play with (assuming you copied numpy.i to your local directory). First, fun.i :

%module fun

%{
#include "f.h"
%}

%include "numpy.i"

%init %{
import_array();
%}

%apply (int DIM1, double* INPLACE_ARRAY1) {(int n, double* x)}
extern void f(int n, double* x);

then fh :

#include "numpy/arrayobject.h"

extern "C" void f(int n, double* x);

run swig:

$ swig -python -c++ fun.i

compile your f.c implementation (which you didn't provide; C compiler is fine), then link:

$ g++ -O2 -o _fun.so -shared fun_wrap.cxx f.o `python3-config --includes` -fPIC -I`python -c 'import numpy; print(numpy.get_include())'` -Wno-cpp

and use:

>>> import fun
>>> import numpy as np
>>> x = np.array(range(10), dtype=np.double)
>>> fun.f(x)
>>>

So now, if I check nm _fun.so | grep PyArray_API nm _fun.so | grep PyArray_API , I get:

0000000000009740 b _ZL11PyArray_API

so it's in the data section and not a symbol to be resolved, but note that the name is mangled and so only resolvable by C++.

EDIT: (As discussed in the comment below.)

There is a strong PyArray_API data symbol in numpy's _multiarray_umath submodule (on my system anyway). I don't think the following is a solution, but it may help figuring out where the problem might be as in principle, the "import_array" part should take care of the same.

Compare the result of this:

>>> import numpy
>>> import fun # the SWIG module, test in your case I think

versus this:

>>> import numpy.core._multiarray_umath as um
>>> import ctypes
>>> h = ctypes.CDLL(um.__file__,  ctypes.RTLD_GLOBAL)
>>> import fun # or import test if that's the name

This may show whether the reason it works for me and not for you is due to differences in our respective numpy installations. (Both work for me.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM