I use Swig.(Mac os 10.13)
My shell script:
swig -c++ -python -o example_wrap.cpp example.i
g++ -c -std=c++17 -fPIC example.cpp
g++ -c -std=c++17 -fPIC example_wrap.cpp -o example_wrap.o \
-I/usr/local/Cellar//python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/include/python3.7m
ld -bundle -macosx_version_min 10.13 -flat_namespace \
-undefined suppress -o _example.so *.o
I spent enough time to seek how to create C++ dynamic library for Python, but I have never used the last line.Most often I create a library from an IDE.
g++ -shared is more familiar, but it doesn't work.
Many such errors appear:
Undefined symbols for architecture x86_64:
"_PyArg_ParseTuple", referenced from:
_wrap_printTree(_object*, _object*) in example_wrap.o
I know about this methods from Python.h.
So, the questions are - how does the last line work(ld -bundle ...)? Are there other methods to create the dynamic library?How can I use g++ -shared?
Here is a small CMakeLists.txt that should work for the example you posted:
cmake_minimum_required(VERSION 3.10) # change this to your needs
project(foo VERSION 0.0 LANGUAGES CXX C)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_SWIG_FLAGS "")
add_library(exampleImpl SHARED example.h example.cpp)
target_compile_features(exampleImpl PUBLIC cxx_std_17)
set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
swig_add_library(example LANGUAGE python SOURCES example.i)
swig_link_libraries(example ${PYTHON_LIBRARIES} exampleImpl)
To make sure cmake uses the right python library, you can pass an appropriate option upon configure time, see here.
Related
I am trying to build a hello world C++ Python extension using boost-python.
I got the following source code from https://www.mantidproject.org/Boost_Python_Introduction:
// test.cpp
#include <iostream>
#include <boost/python.hpp>
void sayHello()
{
std::cout << "Hello, Python!\n";
}
BOOST_PYTHON_MODULE(test) // Name here must match the name of the final shared library, i.e. mantid.dll or mantid.so
{
boost::python::def("sayHello", &sayHello);
}
However, when I try to compile using the following command:
g++ -fPIC -I/usr/include/python3.6m test.cpp -c
g++ -shared test.o -o test.so -I/usr/include/python3.6m -I/lib64/libboost_python3
This command compiles successfully the code and creates a library file test.so.
However, when I try to import the module in python3, I get the following error:
ImportError: /home/yt/C++/test.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv
The link Import Error on boost python hello program seems to suggest the command
I used above would solve the problem by adding -I/usr/include/python3.6m and -I/lib64/libboost_python3, but it does not.
What am I doing wrong?
Thanks!
OS: Fedora 29 x86_64
Thanks guys!
The problem was the linker command. The correct one is:
g++ -fPIC -I/usr/include/python3.6m test.cpp -c
g++ -L /lib64 -shared test.o -o test.so -lpython3.6m -lboost_python3
Now it works on Fedora 29
I'm trying to cross compile Tensorflow for Raspberry PI3 with help of Tensorflow build_raspberry_pi.sh but I'm getting error and I have followed the below steps:-
1: Installing Bazel 0.10.0,
2: Cloning Tensorflow from git and doing a checkout of r1.5,
3: Running the script present inside /tensorflow/tools/ci_build/pi/, The script is build_raspberry_pi.sh.
I'm cross compiling it for raspberry Pi 3 and getting the below error during the compilation:
ERROR: /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/grpc/BUILD:431:1: C++ compilation of rule '#grpc//:gpr_base' failed (Exit 1): arm-linux-gnueabihf-gcc failed: error executing command
(cd /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/execroot/org_tensorflow && \ exec env - \
PATH=/home/baladev/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin \
PWD=/proc/self/cwd \
PYTHON_BIN_PATH=/usr/bin/python \
PYTHON_LIB_PATH=/usr/local/lib/python2.7/dist-packages \
TF_NEED_CUDA=0 \
TF_NEED_OPENCL_SYCL=0 \ /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/arm_compiler/bin/arm-linux-gnueabihf-gcc
-U_FORTIFY_SOURCE '-D_FORTIFY_SOURCE=1' -fstack-protector -DRASPBERRY_PI -g0 -O2 -DNDEBUG -ffunction-sections -fdata-sections -DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK '-march=armv7-a' '-mfpu=neon-vfpv4' '-std=gnu11' '-DS_IREAD=S_IRUSR' '-DS_IWRITE=S_IWUSR' -O3 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 -funsafe-math-optimizations -ftree-vectorize -fomit-frame-pointer '-std=c++11' -isystem /usr/include/arm-linux-gnueabihf -isystem /usr/include/python2.7
-isystem /usr/include/ -MD -MF bazel-out/armeabi-opt/bin/external/grpc/_objs/gpr_base/external/grpc/src/core/lib/support/subprocess_posix.pic.d '-frandom-seed=bazel-out/armeabi-opt/bin/external/grpc/_objs/gpr_base/external/grpc/src/core/lib/support/subprocess_posix.pic.o'
-fPIC '-DGRPC_ARES=0' -D__CLANG_SUPPORT_DYN_ANNOTATION__ -iquote external/grpc -iquote bazel-out/armeabi-opt/genfiles/external/grpc
-iquote external/bazel_tools -iquote bazel-out/armeabi-opt/genfiles/external/bazel_tools -iquote external/com_google_absl -iquote bazel-out/armeabi-opt/genfiles/external/com_google_absl -isystem external/grpc/include -isystem bazel-out/armeabi-opt/genfiles/external/grpc/include -isystem external/bazel_tools/tools/cpp/gcc3 -Wno-builtin-macro-redefined '-D__DATE__="redacted"' '-D__TIMESTAMP__="redacted"' '-D__TIME__="redacted"' -no-canonical-prefixes
-fno-canonical-system-headers -c external/grpc/src/core/lib/support/subprocess_posix.cc -o bazel-out/armeabi-opt/bin/external/grpc/_objs/gpr_base/external/grpc/src/core/lib/support/subprocess_posix.pic.o) cc1plus: warning: command line option '-std=gnu11' is valid for C/ObjC but not for C++ In file included from external/grpc/src/core/lib/support/subprocess_posix.cc:33:0: /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/arm_compiler/bin/../arm-linux-gnueabihf/sysroot/usr/include/sys/wait.h:101:3: error: redeclaration of 'P_ALL' P_ALL, /* Wait for any child. */ ^ In file included from /usr/include/stdlib.h:41:0,
from external/grpc/src/core/lib/support/subprocess_posix.cc:30: /usr/include/bits/waitflags.h:52:3: note: previous declaration 'idtype_t P_ALL' P_ALL, /* Wait for any child. */ ^ In file included from external/grpc/src/core/lib/support/subprocess_posix.cc:33:0: /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/arm_compiler/bin/../arm-linux-gnueabihf/sysroot/usr/include/sys/wait.h:102:3: error: redeclaration of 'P_PID' P_PID, /* Wait for specified process. */ ^ In file included from /usr/include/stdlib.h:41:0,
from external/grpc/src/core/lib/support/subprocess_posix.cc:30: /usr/include/bits/waitflags.h:53:3: note: previous declaration 'idtype_t P_PID' P_PID, /* Wait for specified process. */ ^ In file included from external/grpc/src/core/lib/support/subprocess_posix.cc:33:0: /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/arm_compiler/bin/../arm-linux-gnueabihf/sysroot/usr/include/sys/wait.h:103:3: error: redeclaration of 'P_PGID' P_PGID /* Wait for members of process group. */ ^ In file included from /usr/include/stdlib.h:41:0,
from external/grpc/src/core/lib/support/subprocess_posix.cc:30: /usr/include/bits/waitflags.h:54:3: note: previous declaration 'idtype_t P_PGID' P_PGID /* Wait for members of process group. */ ^ In file included from external/grpc/src/core/lib/support/subprocess_posix.cc:33:0: /home/baladev/.cache/bazel/_bazel_baladev/da0e175f87e998fe3d550279550cec2c/external/arm_compiler/bin/../arm-linux-gnueabihf/sysroot/usr/include/sys/wait.h:104:3: error: conflicting declaration 'typedef enum idtype_t idtype_t' } idtype_t; ^ In file included from /usr/include/stdlib.h:41:0,
from external/grpc/src/core/lib/support/subprocess_posix.cc:30: /usr/include/bits/waitflags.h:55:3: note: previous declaration as 'typedef enum idtype_t idtype_t' } idtype_t; ^ INFO: Elapsed time:
984.156s, Critical Path: 40.58s FAILED: Build did NOT complete successfully
Am I missing something which is needed for cross compilation?
I have anaconda Python first on my path, but a simple Python embedding example shows my Mac system python version instead, even though ProgramFullPath correctly points to anaconda python. Is there a way to correctly find / use anaconda python?
Minimal example:
#include <Python.h>
#include <stdio.h>
int main(void) {
Py_Initialize();
printf("Python version:\n%s\n", Py_GetVersion());
printf("Python Program Full Path:\n%s\n", Py_GetProgramFullPath());
Py_Finalize();
return 0;
}
I compile with,
gcc `python-config --cflags` example.c `python-config --ldflags`
or, expanding the results of the python-config calls,
gcc -I/Users/ryandwyer/anaconda/include/python2.7 \
-I/Users/ryandwyer/anaconda/include/python2.7 \
-fno-strict-aliasing -I/Users/ryandwyer/anaconda/include \
-arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes \
example.c -lpython2.7 -ldl -framework CoreFoundation -u _PyMac_Error
Running the program gives,
Python version:
2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
Python Program Full Path:
/Users/ryandwyer/anaconda/bin/python
This seems to be the same problem as Embed python in c++: choose python version. I have also tried setting PYTHONHOME, Py_SetProgramName, Py_SetPythonHome, but cannot get Python_GetVersion() to return the anaconda version.
There was a partial answer in the post you linked.
Option 1: Run your program as follows
LD_LIBRARY_PATH=/path_to_anaconda/lib ./program
Option 2: Run the following command in the terminal, then run your program
export LD_LIBRARY_PATH=/path_to_anaconda/lib
./program
Option 3: Add the following line to the end of your .bashrc file
LD_LIBRARY_PATH=/path_to_anaconda/lib
Why do you have to do this when embedding python, but not when running the interpreter normally? I have no idea, but if some Python/C wizard stumbles on this post I'd love to know why.
I am developing a python system with some core dlls accessed via ctypes. I have reduced the problem to this condition: execute a module that loads (no need to call) two dlls, one of which calls printf -- this error will occur in exit.
This application has requested the Runtime to terminate it in an
unusual way. Please contact the application's support team for more
information.
My environment:
- Windows 7, SP1
- Python 2.7.8
- MinGW v 3.20
This test case is adapted from a tutorial on writing dlls with MinGW:
/* add_core.c */
__declspec(dllexport) int sum(int a, int b) {
return a + b;
}
/* sub_core.c */
#include <stdio.h>
__declspec(dllexport) int sum(int a, int b) {
printf("Hello from sub_core.c");
return a - b;
}
prog.py
import ctypes
add_core_dll = ctypes.cdll.LoadLibrary('add_core.dll')
add_core_dll = ctypes.cdll.LoadLibrary('sub_core.dll')
> make
gcc -Wall -O3 -g -ansi -c add_core.c -o add_core.o
gcc -g -L. -ansi -shared add_core.o -o add_core.dll
gcc -Wall -O3 -g -ansi -c sub_core.c -o sub_core.o
gcc -g -L. -ansi -shared sub_core.o -o sub_core.dll
>python prog.py
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
and pops up a message dialog to the same effect: "python.exe has stopped working ...".
Note that the programs execute as expected and produce normal output. This error at termination is just a big nuisance I'd like to be rid of.
the same happens for:
Windows 7 Enterprise, SP1
Python 2.7.11
mingw32-g++.exe 5.3.0
I want to write a python extension in c. I work on Mac, I took a code from here:
#include <Python.h>
static PyObject* say_hello(PyObject* self, PyObject* args)
{
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
static PyMethodDef HelloMethods[] =
{
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
inithello(void)
{
(void) Py_InitModule("hello", HelloMethods);
}
I compile it:
gcc -c -o py_module.o py_module.c -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/
gcc -o py_module py_module.o -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/ -lm
But I get this error:
Undefined symbols for architecture x86_64:
"_PyArg_ParseTuple", referenced from:
_say_hello in py_module.o
"_Py_InitModule4_64", referenced from:
_inithello in py_module.o
"__Py_NoneStruct", referenced from:
_say_hello in py_module.o
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [py_module] Error 1
How comes python doesn't support X86_64 architecture?
Two things:
You need to link your extension as a shared object (you're attempting to link an executable, which is why the linker is looking for main());
You need to link against the Python static library (-lpython).
Query the python env path with these commands:
$python-config --includes
-I/usr/include/python2.6 -I/usr/include/python2.6
$python-config --ldflags
-lpthread -ldl -lutil -lm -lpython2.6
generate .o file:
$ g++ -fPIC -c -I/usr/include/python2.6 -I/usr/include/python2.6 xx.cpp
generate .so file:
g++ -shared xx.o -o xx.so
Thanks to #NPE #glglgl and anatoly here is my Makefile:
DIR=/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/
CC=gcc
CFLAGS=-I$(DIR)
ODIR=.
LIBS_DIR=/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/
LIBS=-lpython2.7
_DEPS =
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = py_module.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
py_module: $(OBJ)
gcc -shared $^ $(CFLAGS) -I$(LIBS_DIR) $(LIBS) -o $#
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
makefile template had been taken from here.
In order to find the paths, one may use python-config --ldflags
and python-config --includes