SWIG Python wrappers crash on Mac OSX - python

I am trying to create a simple SWIG Python wrapper for a C function, but it always crashes with
Fatal Python error: PyThreadState_Get: no current thread
I read that this kind of error is caused by using different versions of python when building/linking and when running, but as far as I can tell this is not the case here.
I downloaded, build and installed a brand new python 3.4.4. I have verified that the files I am using are the new ones.
I do:
swig -python -o example_wrap.c -I. -I/usr/local/include/python3.4m example.i
cc -fPIC -I. -I/usr/local/include/python3.4m -c example.c
cc -fPIC -I. -I/usr/local/include/python3.4m -c example_wrap.c
cc -shared -o _example.so example.o example_wrap.o /usr/local/lib/libpython3.4m.a
/usr/local/bin/python3.4 -c "import example"
Just to be sure, instead of cc I tried clang and gcc-mp-4.9 (from MacPorts), all with the same result.
Fatal Python error: PyThreadState_Get: no current thread
This works perfectly fine on Linux. I don't believe I am linking against any of the Frameworks (but python3.4 does).
What am I missing here?
Here is the code:
example.h
#ifndef HELLO_H
#define HELLO_H
extern void hello();
#endif
example.c
#include <stdio.h>
void hello() {
printf("Hello\n");
}
example.i
%module example
%{
#include "example.h"
%}
%include "example.h"
Linking is as follows:
otool -L /usr/local/bin/python3.4
/usr/local/bin/python3.4:
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1258.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
otool -L _example.so
_example.so:
_example.so (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

I think you are supposed to link with:
cc -shared -o _example.so example.o example_wrap.o -L/usr/local/lib -lpython3.4m
Otherwise, some symbols from libpython3.4m.a may be included in your shared object, and then are available twice when importing from python (?).
In any case, on my system (OSX 10.11, with MacPorts Python 3.4), both do work.

Related

Which $path is needed so g++/pybind11 could locate Python.h?

I started using pybind11 (on Ubuntu 16.04 with Python 2.7).
To test the waters, I created a do-nothing wrapper around my c++ library. Alas, the compilation is unable to find Python.h:
$ g++ -std=c++0x -fPIC -pedantic -g -Wno-missing-field-initializers -Wno-switch -Wno-multichar -ftree-vectorize -ftree-vectorize -mssse3 backend.h uvc-v4l2.cpp wrap.cpp -o wrap.so
backend.h:4:9: warning: #pragma once in main file
#pragma once
^
In file included from /usr/local/include/pybind11/pytypes.h:12:0,
from /usr/local/include/pybind11/cast.h:13,
from /usr/local/include/pybind11/attr.h:13,
from /usr/local/include/pybind11/pybind11.h:36,
from wrap.cpp:1:
/usr/local/include/pybind11/common.h:72:20: fatal error: Python.h: No such file or directory
#include <Python.h>
^
compilation terminated.
However, I do seem to have the file:
$ find /usr -name Python.h
/usr/include/python2.7/Python.h
/usr/include/python3.5m/Python.h
Which (path?) should I correct so g++ would be able to locate Python.h?
Notes:
$ apt list | grep -iE -- '^python.-dev|^python-dev'
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
python-dev/xenial,now 2.7.11-1 amd64 [installed]
python3-dev/xenial,now 3.5.1-3 amd64 [installed]
$ dpkg -S Python.h
libpython2.7-dev:amd64: /usr/include/python2.7/Python.h
libpython3.5-dev:amd64: /usr/include/python3.5m/Python.h
$ dpkg -L python2.7-dev
/.
/usr
/usr/bin
/usr/share
/usr/share/man
/usr/share/man/man1
/usr/share/doc
/usr/share/doc/python2.7
/usr/share/doc/python2.7/x86_64-linux-gnu
/usr/share/doc/python2.7/x86_64-linux-gnu/test_results.gz
/usr/share/doc/python2.7/x86_64-linux-gnu/pybench.log.gz
/usr/share/doc/python2.7/gdbinit.gz
/usr/share/doc/python2.7/HISTORY.gz
/usr/share/doc/python2.7/README.valgrind.gz
/usr/share/doc/python2.7/README.maintainers
/usr/bin/python2.7-config
/usr/share/man/man1/python2.7-config.1.gz
/usr/share/doc/python2.7-dev
-I/usr/include/python2.7
The -I flag adds the directory to the list of directories to be searched for header files. If you were to instead want the python3.5 equivalent, you'd replace 2.7 with 3.5m
A more reliable way to get this flag is to use pkg-config. For instance:
$ pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7
$ pkg-config --cflags python3
-I/usr/include/python3.6m -I/usr/include/x86_64-linux-gnu/python3.6m

Fatal Python error when using SWIG under OSX

I have troubles using a Python interface generated with SWIG (I have OSX 10.11.12). After compiling and linking everything together as such:
swig -python erk_integrator.i
gcc -c -fPIC -O3 model.c auxiliary_functions.c timing_functions.c
gcc -c -fPIC -O3 erk_integrator.c erk_integrator_wrap.c -I. -I/usr/local/include/python2.7
gcc -lpython -dynamiclib model.o erk_integrator.o erk_integrator_wrap.o auxiliary_functions.o timing_functions.o -o _erk_integrator.so
I try a test script, but Python throws a fatal error:
/usr/local/bin/python test_erk.py
Fatal Python error: PyThreadState_Get: no current thread
Abort trap: 6
But when I run
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 test_erk.py
everything works as it should. However, I need to use /usr/local/bin/python (from Homebrew) instead of the system Python.
I think something goes wrong in the linking step. Many thanks for helping!
This blog post helped me solve it: blog.tim-smith.us/2015/09/python-extension-modules-os-x
It turns out on OSX you need
-undefined dynamic_lookup
instead of
-lpython

boost_python hello example not working

I am trying to get the hello world example for boost python working. I am using OSX, boost 1.55 and python 2.7
Here is my hello.cpp
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
and I have compiled it with the following two lines:
g++ -fPIC -I/usr/include/python2.7/ -I/usr/local/include/ -c hello.cpp
g++ -shared -Wl, -o hello.so hello.o -L/usr/lib -L/usr/local/lib -lpython2.7 -lboost_python
When I try to import it into python by doing import hello.so I get the following error:
ImportError: dynamic module does not define init function (inithello)
Any ideas?
Turns out the name in the BOOST_PYTHON_MODULE must match the name of the library so I changed the linking step to
g++ -shared -Wl, -o hello_ext.so hello.o -L/usr/lib -L/usr/local/lib -lpython2.7 -lboost_python

Embedding Python in C, linking fails with undefined reference to `Py_Initialize'

I am trying to compile the example from the docs https://docs.python.org/2.7/extending/embedding.html and my code looks exactly like the one under 5.1:
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("from time import time, ctime\n"
"print 'Today is', ctime(time())\n");
Py_Finalize();
return 0;
}
I use the following command to compile it which works fine for me and gives me the desired object file:
gcc -c $(python2.7-config --cflags) embedpy.c
To link it I use the following command which ends up in the following error:
gcc $(/usr/bin/python2.7-config --ldflags) embedpy.o
embedpy.o: In function `main':
/home/miguellissimo/embedpy.c:6: undefined reference to `Py_SetProgramName'
/home/miguellissimo/embedpy.c:7: undefined reference to `Py_Initialize'
/home/miguellissimo/embedpy.c:8: undefined reference to `PyRun_SimpleStringFlags'
/home/miguellissimo/embedpy.c:11: undefined reference to `Py_Finalize'
collect2: error: ld returned 1 exit status
I can't find out what I am doing wrong or what I forget to get the example working.
PS: The python2.7-config command gives the following output on my Xubuntu machine:
>>> python2.7-config --cflags
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -fno-stri
ct-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=
4 -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-pr
ototypes
>>> python2.7-config --ldflags
-L/usr/lib/python2.7/config-x86_64-linux-gnu -L/usr/lib -lpthread -ldl -luti
l -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
Libraries have to come after the object files when you are linking, so do:
gcc embedpy.o $(/usr/bin/python2.7-config --ldflags)
Also add --embed to python3-config
On Ubuntu 20.04, Python 3.8, I also needed to pass --embed to python3-config as in:
gcc -std=c99 -ggdb3 -O0 -pedantic-errors -Wall -Wextra \
-fpie $(python3-config --cflags --embed) -o 'eval.out' \
'eval.c' $(python3-config --embed --ldflags)
otherwise -lpython3.8 is not added which leads to missing definitions.
This is my test program:
eval.c
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int main(int argc, char *argv[]) {
(void)argc;
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program);
Py_Initialize();
PyRun_SimpleString(argv[1]);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
test run:
./eval.out 'print(2 ** 3)'
Got the same error on WSL, Ubuntu 18.04, Python3.8, g++ 7.5.
Thanks to Ciro Santilli comment, adding --embed option to python3.8-config solved unresolved symbols problem, but after that I got the following error:
g++ `python3.8-config --cflags --embed` -o cpython.out cpython.cpp `python3.8-config --ldflags --embed`
lto1: fatal error: bytecode stream in file ‘/home/rpovelik/installed/miniconda3/envs/cython/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a’ generated with LTO version 6.0 instead of the expected 6.2
compilation terminated.
lto-wrapper: fatal error: g++ returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
I suppose some people are going to face the same issue so I inspected the similar symptoms here where conda people said something like "don't use default compilers - g++ - because it could cause compatibility issues - use conda specific compilers".
By the way, adding -fno-lto solved my problem with system-wide g++ 7.5. Possibly you can try to change version of the compiler.
I replicated the same problem on Lubuntu14.04 32bit virtual machine running on Win7 machine.
I did the following things to replicate the problem in the first place where the C++ code is written in Eclipse C/C++ IDE. Defined a C++ Eclipse project titled "test". The source file contains the following C++ code which is the same as mentioned above by Miguellissimo.
C++ Code ::
#include "python2.7/Python.h"
int main(int argc, char *argv[]) {
Py_Initialize();
PyRun_SimpleString("print \"Hello, world!\"");
Py_Finalize();
return 0;
}
Errors ::
test.o: In function main':
/home/ros/workspace/test/src/test.cpp:15: undefined reference toPy_Initialize'
/home/ros/workspace/test/src/test.cpp:17: undefined reference to PyRun_SimpleStringFlags'
/home/ros/workspace/test/src/test.cpp:18: undefined reference toPy_Finalize'
collect2: error: ld returned 1 exit status
The output of the following commands was the same as mentioned before by Miguellissimo,
ros#rosPC:~/workspace/test/src$ python2.7-config --cflags
-I/usr/include/python2.7 -I/usr/include/i386-linux-gnu/python2.7 -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes
ros#rosPC:~/workspace/test/src$ python2.7-config --ldflags
-L/usr/lib/python2.7/config-i386-linux-gnu -L/usr/lib -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
Project Properties of C++ Eclipse Project titled "test"::
Inside, I had the following C++ Build Settings
GCC C++ Compiler
Command: g++
All options: -I/opt/ros/indigo/include -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
include paths: /opt/ros/indigo/include
GCC C Compiler
Command: gcc
All options: -I/opt/ros/indigo/include -I/usr/lib/python2.7/config-i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
include paths: /opt/ros/indigo/include
/usr/lib/python2.7/config-i386-linux-gnu
GCC C++ Linker
Command: g++
All options: Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Libraries:
Libraries(-I):
Library search path(-L):
Solution::
Specified the following C++ Build Settings in the Project Properties of C++ Eclipse Project "test"
GCC C++ Compiler
Command: g++
All options: -I/opt/ros/indigo/include -I/usr/include/python2.7 -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
include paths: /opt/ros/indigo/include
/usr/include/python2.7
GCC C Compiler
Command: gcc
All options: -I/opt/ros/indigo/include -I/usr/include/python2.7 -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
include paths: /opt/ros/indigo/include
/usr/include/python2.7
GCC C++ Linker
Command: g++
All options: -L/usr/lib/python2.7/config-i386-linux-gnu
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Libraries:
Libraries(-I): python2.7
Library search path(-L): /usr/lib/python2.7/config-i386-linux-gnu
Result :: Linker errors which resulted previously from the compilation of C++ Eclipse project doesn't occur anymore.
The accepted answer uses system's default library location.
If you are within an anaconda environment, library location may not be found. I tend to give locations more explicitly during linking, like:
gcc embedpy.o -L$(python-config --prefix)/lib $(python-config --ldflags)
This will not work outside anaconda environment in 64-bit library, in which case:
gcc embedpy.o -L$(python-config --prefix)/lib64 $(python-config --ldflags)

g++ linking and swig

I have a cpp file with functions that I'm using in python with SWIG. I use the following commands to compile the source and create the file to use with python.
swig -c++ -python mini.i
g++ -O2 -c mini.cpp -I/usr/include/python2.4 -I/usr/lib/python2.4
g++ -O2 -c mini_wrap.cxx -I/usr/include/python2.4 -I/usr/lib/python2.4
g++ -shared mini.o mini_wrap.o -o _mini.so
I'm trying now to use GSL in my source cpp source file. If I was just compiling the GSL file I would do
g++ -lgsl -lgslcblas -lm -o mini.o mini.cpp
I've tried adding the -lgsl -lgslcblas -lm to the lines for the swig compile but I get
g++: -lgsl: linker input file unused because linking not done
g++: -lgslcblas: linker input file unused because linking not done
g++: -lm: linker input file unused because linking not done
How can I link the gsl libraries? Thanks
Swig does no linking, as the warning message states. Put the -lgsl etc. on the link command, which is your last g++ command.

Categories

Resources