So, i search good tool to integrate my C++ code with python, and at first i looked at boost.python.
I've get hello examle from boost documentation and try to build and run it. Source code is (src/hello.cpp):
#include <Python.h>
#include <boost/python.hpp>
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
Problem 1 - Windows and mingw
I try to build and my result :
g++ -o build\hello.o -c -IE:\Programming\libs\boost_1_48_0 -IE:\Programming\Python\include src\hello.cpp
g++ -shared -o pyhello.dll build\hello.o -LE:\Programming\libs\boost_1_48_0\stage\lib -LE:\Programming\Python\libs -lboost_python-mgw45-mt-1_48 -lpython27 -Wl,--out-implib,libpyhello.a
Creating library file: libpyhello.a
build\hello.o:hello.cpp:(.text+0x20): undefined reference to `_imp___ZN5boost6python6detail11init_moduleEPKcPFvvE'
Also similar 4 undefined errors with boost::python.
My build boost command line : bjam toolset=gcc variant=release
I found similar troubles in google (and on stackoverflow too), but didn't found answer at my case.
Problem 2 - Using module (linux)
At linux platform i've no problem with building module, same source compiled well :
g++ -o build/hello.os -c -fPIC -I/usr/include/python2.7 src/hello.cpp
g++ -o libpyhello.so -shared build/hello.os -lboost_python -lpython2.7
Now, how can i use that? In documentation no words about module naming, quote :
can be exposed to Python by writing a Boost.Python wrapper:
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
That's it. We're done. We can now build this as a shared library. The
resulting DLL is now visible to Python. Here's a sample Python
session:
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
So, my module named: libpyhello.so, but how i can use it in python iterpreter? I try import pyhello, hello_ext, libpyhello - and only with libpyhello interpreter is printed :
ImportError: dynamic module does not define init function (initlibpyhello)
All other variants of import failed with : ImportError: No module named pyhello
UPDATE 2nd question : Solved, *.so module must be named as ID used in BOOST_PYTHON_MODULE. After i change : BOOST_PYTHON_MODULE(hello_ext) to BOOST_PYTHON_MODULE(libpyhello), module is imported well as libpyhello.
It's important that the library file is named like you declare the module here:
BOOST_PYTHON_MODULE(hello_ext)
that is hello_ext.dll or hello_ext.so.
Hi,I have got the same problem as yours under win7 32bit with mingw, however I fixed it at last.
The possible solution is:
When build the lib boost python, use link=shared instead.
like:
bjam stage toolset=gcc --with-python link=shared threading=multi runtime-link=shared variant=release,debug --user-config=user-config.jam cxxflags="-include cmath "
When link,use the BOOST_PYTHON_STATIC_LIB macro explicitly
The following is the sample cmd line:
g++ hello_ext.cpp -shared -O3 -DBOOST_PYTHON_STATIC_LIB -lboost_python -lpython25 -o hello_ext.pyd
To save your time,just add some lines in file boost\python.hpp:
#include <cmath> //fix cmath:1096:11: error: '::hypot' has not been declared
#if defined(__MINGW32__) && defined(_WIN32)
#if !defined(BOOST_PYTHON_SOURCE)
#define BOOST_PYTHON_STATIC_LIB
#endif
#endif
... here,other includes files ...
Then, you can simply use cmd like this:
g++ hello_ext.cpp -shared -lboost_python -lpython25 -o hello_ext.pyd
This shell will be ok, have a try.
Related
linux Debian Buster
go version go1.11.6 linux/amd64
gcc version 8.3.0 (Debian 8.3.0-6)
libmylib.go
package main
import "C"
import (
"fmt"
)
func say(text string) {
fmt.Println(text)
}
func main(){}
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <string>
void say(std::string text);
#endif
main.cpp
#include <string>
#include "mylib.h"
using namespace std;
int main() {
string text = "Hello, world!";
say(text);
return 0;
}
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
g++ -L/path/to/lib/ -lmylib main.cpp -o my-test-program
/usr/bin/ld: /tmp/ccu4fXFB.o: in function 'main':
main.cpp:(.text+0x53): undefined reference to `say(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)' collect2: error: ld returned 1 exit status
with change: package main -> package mylib
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
-buildmode=c-shared requires exactly one main package
You have to use GoString rather than std::string in the C++ version. The error message you are getting is because of the type mismatch, manifesting as a link-time error.
See the cgo reference.
Here's a working example. There's a few differences from yours. The //export directive is needed to include the function in the generated header file, the argument is *C.char rather than string or GoString. The C++ code uses the header generated by cgo, and there has to be a const-removing cast from the static string (because go doesn't have C-like const).
libmylib.go
package main
import "C"
import (
"fmt"
)
//export say
func say(text *C.char) {
fmt.Println(C.GoString(text))
}
func main() {}
main.cpp
#include "libmylib.h"
int main(void) {
say(const_cast<char*>("hello world"));
return 0;
}
commands
This compiles to go file, generating libmylib.so and libmylib.h in the current directory.
go build -o libmylib.so -buildmode=c-shared libmylib.go
The compiles the C++ program, linking it to the shared library above:
g++ -L. main.cpp -lmylib -o hello_program
To run the program, LD_LIBRARY_PATH needs to be set to the current directory. That would be different if program was installed and the shared library put in a sensible place.
LD_LIBRARY_PATH=. ./hello_program
g++ -L/path/to/lib/ -lmylib main.cpp -o test
is probably wrong. Read the invoking GCC chapter of the GCC documentation. Order of arguments to g++ matters a lot.
Also, test(1) could be some existing executable. I recommend to use some other name.
So consider compiling with
g++ -Wall -g -O main.cpp -L/path/to/lib/ -lmylib -o my-test-program
You probably want debugging information (-g), warnings (-Wall) and some optimization (-O)
You did comment
I need to use some functions from a Go file in my C ++ project.
This is curious. I assume your operating system is some Linux. Then, can't you just use inter-process communication facilities between a process running a Go program and another process running your C++ program? Consider perhaps using JSONRPC or HTTP between them. There exist several open source libraries in Go and in C++ to help you.
PS. As I commented, calling C++ code from a Go program could be much simpler. Of course you do need to read the Go documentation and the blog about cgo and probably the C++ dlopen minihowto and some C++ reference.
I tried to describe in the module sample_extension.cc ( https://www.dartlang.org/articles/server/native-extensions) STL string:
#include <string>
using namespace std;
string string_ ("std.string");
and that was enough for the shared library libsample_extension.so to stop being created. Maybe any special rules for creating such libraries or is there a more serious problem? For now, I use the commands:
g++ -fPIC -DDART_SHARED_LIB -c sample_extension.cc
gcc -shared -Wl, -soname, libsample_extension.so -o libsample_extension.so sample_extension.o*
and no errors messages.
I get an error later at the command line on run dart:
$ dart test_sample_synchronous_extension.dart
libsample_extension.so: cannot open shared object file: No such file or directory error: library handler failed
I am trying to use the boost library with QT on windows. I've successfully build the library and also managed to include it in my project. However, on including gmp (#include "boost/multiprecision/gmp.hpp") and creating an object (boost::multiprecision::mpz_int myint;) I get the following error:
C:\Users\Laurenz\Documents\libraries\boost_1_66_0\include\boost\multiprecision\gmp.hpp:31: error: gmp.h: No such file or directory
And indeed, I haven't been able to find any such file in the boost directory. What did I do wrong?
Install the dependency and link to it. (See What is an undefined reference/unresolved external symbol error and how do I fix it?)
Alternatively, consider not using GMP, using cpp_int.hpp instead.
Since you already installed the GMP library, here's the last step:
Live On Coliru
#include <boost/multiprecision/gmp.hpp>
#include <iostream>
int main() {
boost::multiprecision::mpz_int i("1238192389824723487823749827349879872342834792374897923479");
std::cout << pow(i, 3) << "\n";
}
Note the -lgmp flag at the end of the compile/link command:
g++ -std=c++11 -O2 -Wall -Wextra -pedantic main.cpp -o demo -lgmp
Running it:
./demo
1898298004808110659499396020993351679788129852647955073547637871096272981567489303363372689896302906549189545322451852317205769760555889831589125591739044248515246136031239
I have a fresh install of OS X 10.11.4 that I immediately installed the Xcode toolchain on, then Homebrew, then Boost 1.60. In order to test that everything had gone well, I wrote the following code on my Desktop.
#include <iostream>
#include <boost/filesystem.hpp>
int main() {
boost::filesystem::path new_directory("hello");
boost::filesystem::create_directory(new_directory);
}
I then attempted to compile it as I usually have done with the following command.
$ clang++ test.cpp -o test -lboost_system -lboost_filesystem
I received the following error.
test.cpp:3:10: fatal error: 'boost/filesystem.hpp' file not found
#include <boost/filesystem.hpp>
This is how I have always compiled projects that link Boost in the past. I'm assuming that I have probably forgotten a step along the way that allows clang to search a specific path to dynamically link the libraries. What should I change in order for this compilation command to work?
For me, boost has been compiled and installed into a subdirectory of my home directory, so you'll need to modify the paths as appropriate for your homebrew installation:
flags="-std=c++1z -I/${HOME}/local/include -L${HOME}/local/lib -lboost_filesystem -lboost_system"
c++ ${flags} -o jared jared.cpp
First get the location of boost by doing the following:
brew info boost
From the image above, you can see that my location is
/usr/local/Cellar/boost/1.66.0
Then, to compile, use the following:
c++ -I /usr/local/Cellar/boost/1.66.0 main.cpp -o boost
I have code written in C++:
#include <boost/python.hpp>
char const* greet()
{
return "Yay!";
}
BOOST_PYTHON_MODULE(libtest)
{
using namespace boost::python;
def("greet", greet);
}
Now i want to import this dynamic library to python by:
import libtest
But I get:
ImportError: /usr/lib/libboost_python.so.1.54.0: undefined symbol: PyClass_Type
What should I do? My OS is Arch Linux.
Ok, I have found solution for this problem. The simplest options is to compile by:
g++ testing.cpp -I/usr/include/python3.3m -I/usr/include/boost -lboost_python3 -lpython3.3m -o testing.so -shared -fPIC
Previously I used -lboost_python instead of -lboost_python3 ... But this solution is not cross platform so we can achieve this by cmake:
cmake_minimum_required(VERSION 2.6)
find_package(Boost 1.54 EXACT REQUIRED COMPONENTS python3)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} "/usr/include/python3.3m/" )
find_package(PythonLibs)
ADD_LIBRARY(testing SHARED testing.cpp)
TARGET_LINK_LIBRARIES(testing ${Boost_LIBRARIES} ${PythonLibs_LIBRARIES})
Of course "/usr/include/python3.3m" won't be path to pythons include directory in all linux distros.
Use the same version of Python when building both Boost.Python and the libtest module, as well as when importing libtest.
PyClass_Type is is part of the Python 2 C API and not part of the Python 3 C API. Hence, the Boost.Python library was likely built against Python 2. However, it is being loaded by a Python 3 interpreter, where the PyClass_Type is not available.