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
Related
I am trying to compile the example C application embedding Python (from here https://docs.python.org/3.8/extending/embedding.html)
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
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); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
I'm using gcc options generated by python3.8-config.
Thus, compile and link are done as follows:
gcc $(python3.8-config --cflags) -c embePy.c -o embePy.o
gcc $(python3.8-config --ldflags) -o embePy.o
Compiling goes smoothly, whereas linking throws an error:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
Just in case:
$ /usr/bin/python3-config --cflags
-I/usr/include/python3.8 -I/usr/include/python3.8 -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.8-CoVRmP/python3.8-3.8.10=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O3 -Wall
$ /usr/bin/python3-config --ldflags
-L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib -lcrypt -lpthread -ldl -lutil -lm -lm
I don't have experience with manual control of gcc's options, all what I've done was compilation from inside IDE's with automatically set flags. Can anybody help me to identify the problem? Thank you.
I solved the problem, thank #deamentiaemundi and the post from here: https://stackoverflow.com/a/27672776/9256844
To avoid "relocation R_X86_64_32", compile with -fPIE:
gcc $(python3.8-config --cflags) -fPIE -c embePy.c -o embePy.o
To link against the Python libs, I had to put my object file before the python's flags AND manually add -lpython3.8:
gcc embePy.o $(python3.8-config --ldflags) -lpython3.8 -o embePy
Looks like my version of Python mistakenly outputs duplicated flag -lm instead of -lpython3.8 (Python 3.8.10):
$ python3.8-config --ldflags
-L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib -lcrypt -lpthread -ldl -lutil -lm -lm
I need to access the cuda modules of opencv in C++ from python. I tried wrapping the c++ functions using Boost however I get the following error.
ImportError: ../build/lib.linux-x86_64-2.7/pyBoostHOG.so: undefined
symbol: _ZN2cv4cuda6Stream4NullEv.
Is there any way by which I can access the opencv cuda modules from python?
Thanks in advance..
I was facing the same error. And this is how I was compiling the .so file:
g++ `pkg-config opencv4 --cflags --libs` -fPIC -c flow.cpp
g++ -Wall -O3 -shared -o flow.so flow.o `pkg-config opencv4 --cflags --libs`
The error was resolved when I changed my make file to the following:
g++ `pkg-config opencv4 --cflags --libs` -fPIC -c flow.cpp
g++ -Wall -O3 -shared flow.o -o flow.so `pkg-config opencv4 --cflags --libs`
I had the same error.
I figured out that I must include opencv2/core/cuda.hpp file (symbol _ZN2cv4cuda6Stream4NullEv reffers to: cv::cuda::Stream::Null()
But this doesn't solve the problem, because when I tried to make wrap thought swig and include these file, new error:
.../include/opencv2/core/cuda.hpp:317: Error: Syntax error in input(1).
is displayed.
Compiling another program using cv::cuda::Stream::Null() cause not error.
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.
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)
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.