Boost.Python Hello World on Mac OS X - python

I am trying to setup and compile the Hello World example for Boost.Python: http://www.boost.org/doc/libs/1_57_0/libs/python/doc/tutorial/doc/html/python/hello.html
I installed bjam, boost, boost-build, and boost-python from Homebrew:
brew install bjam
brew install boost
brew install boost-build
brew install boost-python
My python install is also via Homebrew. I am not sure how to properly modify the example Jamroot file so that it is compatible with my system setup. I changed the boost path to : /usr/local/Cellar/boost; but I'm not sure of the other paths that need to be changed. The current setup gives me the following error:
> bjam
notice: no Python configured in user-config.jam
notice: will use default configuration
Jamroot:26: in modules.load
*** argument error
* rule use-project ( id : where )
* called with: ( boost : /usr/local/Cellar/boost; project : requirements <library>/boost/python//boost_python <implicit-dependency>/boost//headers : usage-requirements <implicit-dependency>/boost//headers )
* extra argument project
/usr/local/share/boost-build/build/project.jam:1138:see definition of rule 'use-project' being called
/usr/local/share/boost-build/build/project.jam:311: in load-jamfile
/usr/local/share/boost-build/build/project.jam:64: in load
/usr/local/share/boost-build/build/project.jam:145: in project.find
/usr/local/share/boost-build/build-system.jam:535: in load
/usr/local/share/boost-build/kernel/modules.jam:289: in import
/usr/local/share/boost-build/kernel/bootstrap.jam:139: in boost-build
/usr/local/share/boost-build/boost-build.jam:8: in module scope

Summary
Don't use BJAM it's a waste of your time - I am assuming your interest in BJAM is a side-product of getting your code to actually work
Here is the quick-link to my github page where I do a hello_world example using namespace boost::python
See my github for linking multiple boost files into one import library
Longer Answer
I have exactly the same setup as you. I spent ages getting this to work as the documentation is really shady (as you know) and before you know it you go down some weird rabbit hole trying to hack make files and BJAM installations.
You can use a setup.py as you would normally with C code as follows...
Installation
You can obtain the correct boost-python through homebrew via the command:
brew install boost --with-python --build-from-source
I think brew install boost should work but it's a big install and life is short to do it twice
Boost code
Assume the following code in hello_ext.cpp
#include <boost/python.hpp>
char const* greet()
{
return "Greetings!";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
Python setup
Then you can write setup.py file as
from distutils.core import setup
from distutils.extension import Extension
hello_ext = Extension(
'hello_ext',
sources=['hello_ext.cpp'],
libraries=['boost_python-mt'],
)
setup(
name='hello-world',
version='0.1',
ext_modules=[hello_ext])
Compiling
The following example can be used by:
python setup.py build_ext --inplace
which will create the following build/ directory and file:
build/
hello_ext.so
Running
This can be directly now called by python with:
In [1]: import hello_ext
In [2]: hello_ext.greet()
Out[2]: 'Greetings!'

Related

Boost Python Basic function returning int: SIGSEGV

I successfully used Boost Python to write C++ functions with Numpy array arguments.
But I'm struggling with a very basic case: when my function has to return a value. There's no problem until I try to read the int returned by my function.
I strongly suspect my setup has something to do with this, but I'm not sure where to begin. I commented my CMakeLists.txt to explain how I did setup all the libs.
I tried to play with return_value_policy but it seems irrelevant for simple scalar values.
Environment:
MacOS 11.0.1 (20B50)
CLion for C++ edition and build
Pycharm to run Python code, configured using conda environment with Python 3.8
Boost setup described in CMakeLists.txt
C++ code:
int testFunction() {
std::cout << "Test Function 1\n";
return 1;
}
void testFunction2() {
std::cout << "Test Function 2\n";
}
BOOST_PYTHON_MODULE (mylib) {
np::initialize();
py::def("test_function", testFunction);
py::def("test_function_2", testFunction2);
}
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(mylib_project)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
find_package(PythonInterp 3)
find_package(PythonLibs 3)
# Standard boost installation
# Download boost https://www.boost.org/users/download/ and unzip
# Inside boost dir:
# ./bootstrap.sh
# ./b2
# ./b2 install
# Other (brew / macports) install will have all chances to fail (at the time of writing)
# Components should be found in path with name libboost_NAME.dylib, eg: /usr/local/lib/libboost_numpy38.dylib
# This is additional to standard boost installation
# For both python38 and numpy38 to be produced, you have to:
# - be in the right python environment (conda python 3.8 for example)
# - install numpy: pip install numpy
# - inside boost dir:
# ./bootstrap.sh --with-libraries=python
# ./b2
# ./b2 install
find_package(Boost 1.75.0 COMPONENTS python38 numpy38 REQUIRED)
# Python library, will produce a mylib.so file
python_add_module(mylib python-mylib.cpp)
target_include_directories(mylib PRIVATE ${PYTHON_INCLUDE_DIRS})
target_include_directories(mylib PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(mylib ${PYTHON_LIBRARY})
target_link_libraries(mylib ${Boost_PYTHON_LIBRARY})
target_link_libraries(mylib ${Boost_LIBRARIES})
I'm then producing a mylib.so that I provide to the path of my python code.
Python code:
if __name__ == '__main__':
mylib.test_function_2()
result = mylib.test_function()
print(result)
Output:
Test Function 2
Test Function 1
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
My naive question is: how to avoid this crash ?
But after some further investigations (see comments) I'd rather ask: how can I proceed to find (and then probably fix) the cause of this issue in my setup ?

How to (hermetically) include Python interpreter in Bazel to build Python library (sdist)

How can I (hermetically) include python as an (executable) input to my genrule?
Conceptually, I'm aware of the following approaches:
include a python interpreter in the source repo at third_party/python
have Bazel fetch python ala rules-go
There also seem to be a couple methods for doing so:
py_runtime
py_toolchain (doesn't seem to be available yet)
py_distribution_package (doesn't seem to be available yet)
genrules.tools
genrules.toolchains
Example:
I have a python library:
myproject
- setup.py
- mylibrary
- __init__.py
- myfunction.py
I'd like to produce a pip install-able distribution with Bazel so that I can do:
pip install <path/to/distribution>
python
>>> from mylibrary.myfunction import helloworld
>>> helloworld()
I added a (empty) WORKSPACE file at myproject/WORKSPACE and followed the example in this medium article:
# myproject/BUILD
genrule(
name = "mylibrary_sdist",
srcs = glob(["**/*.py"]),
outs = ["mylibrary.tar.gz"],
cmd = "python setup.py sdist && mv dist/mylibrary*.tar.gz $(location mylibrary.tar.gz)"
)
This works (ie. produces bazel-genfiles/mylibrary.tar.gz), but I'm shelling out to python.
How can I (hermetically) include python as an (executable) input to my genrule?
Unless I'm misunderstanding your question, this should just be a matter of passing the actual path to your target python executable. I would check the python executable into the third_party dir and instead of invoking your genrule using simply python I'd pass the relative path to that executable relative to WORKSPACE.

Cython Compilation Error: dynamic module does not define module export function

I am building a package in Cython. I am using the following as the structure for setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy
import scipy
extensions = [
Extension("xxxxx",["xxxx/xxxxx.pyx"],
include_dirs=[numpy.get_include(),"."]),
Extension("nnls",["xxxxx/xxxxx.pyx"],
include_dirs=[numpy.get_include(),"."]),
]
setup(
name='xxxxxx',
version='0.0.0',
description='''********''',
url='xxxxxxx',
author='xxxxx',
author_email='xxxxx',
packages=[
'xxxxx',
],
install_requires=[
'cython',
'numpy',
'scipy',
],
ext_modules=cythonize(extensions),
)
However, I am getting an error upon installation in Python 3. It is working in Python 2 however, it is not compiling in Python 3 having the following error:
dynamic module does not define module export function
How can I solve this problem? Is the structure of the setup.py the reason why this is not compiling?
You need to call setup.py with Python 3 (python3 setup.py build_ext, maybe --inplace). It's because Python 3 defines a different name for the init function called when the module starts, and so you need to build it using Python 3 to ensure the correct name is generated.
See dynamic module does not define init function (PyInit_fuzzy) and How to specify Python 3 source in Cython's setup.py? for slightly more detail (it's bordering on a duplicate of these questions, but isn't quite in my view)
I experienced this and found that I had to use the same name of .pyx as the module name, e.g.
makefile:
# (default)
# INSTALL_DIR:=/usr/lib/python3.6/site-packages
# (my venv)
INSTALL_DIR:=/home/<username>/python3_venv/lib/python3.6/site-packages
all:
sudo python3 setup_myproj.py install --install-lib ${INSTALL_DIR}
setup_myproj.py
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension("myproj",
sources=["myproj.pyx", "myCppProjFacade.cpp"],
<etc>
language="c++"
)
setup(name="myproj",
version="0.0.1",
ext_modules=cythonize(ext))
client module, run after installing to venv
import myproj as myCppProjWrapper
...
I also found that if the "myproj" names are different, under <python-lib-dir>/<python-vers>/site-packages the .so and .egg-info names are different and the client fails to load it.
In addition I found that the client's environment does not need to have the cython package installed.
I had the same error for torchvision. FIxed it by downgrading the installation versions:
pip install torch==1.2.0+cu92 torchvision==0.4.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html

Error installing/compiling grpc on Ubuntu

I have protobuf compiler version 3.0 and need to install grpc and grpc python plugin. Following the tutorial, I added deb http://http.debian.net/debian jessie-backports main to my sources.list file and did sudo apt-get update and sudo apt-get install libgrpc-dev which returned
Package libgrpc-dev is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
E: Package 'libgrpc-dev' has no installation candidate
So, I decided to compile it from source as mentioned in INSTALL notes and did:
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
However, on the make step, I get
[MAKE] Generating cache.mk
make: Circular /home/vagrant/grpc2/grpc/libs/opt/libboringssl.a <- /home/vagrant/grpc2/grpc/libs/opt/libboringssl.a dependency dropped.
[C] Compiling third_party/boringssl/crypto/bio/connect.c
third_party/boringssl/crypto/bio/connect.c: In function 'split_host_and_port':
third_party/boringssl/crypto/bio/connect.c:127:17: error: declaration of 'close' shadows a global declaration [-Werror=shadow]
cc1: all warnings being treated as errors
make: *** [/home/vagrant/grpc2/grpc/objs/opt/third_party/boringssl/crypto/bio/connect.o] Error 1
On switching to the release-0_11 branch, running make results in
[HOSTCXX] Compiling src/compiler/csharp_generator.cc
src/compiler/csharp_generator.cc:47:43: error: 'google::protobuf::compiler::csharp::GetUmbrellaClassName' has not been declared
src/compiler/csharp_generator.cc: In function 'void grpc_csharp_generator::{anonymous}::GenerateServiceDescriptorProperty(grpc::protobuf::io::Printer*, const ServiceDescriptor*)':
src/compiler/csharp_generator.cc:237:62: error: 'GetUmbrellaClassName' was not declared in this scope
make: *** [/home/vagrant/grpc2/grpc/objs/opt/src/compiler/csharp_generator.o] Error 1
I can't figure out how to install this. Any help would be appreciated.
For me the issue got fixed after i made change in the file as:
diff --git a/src/compiler/csharp_generator.cc
b/src/compiler/csharp_generator.cc
index 7b497df..5a8746d 100644
--- a/src/compiler/csharp_generator.cc
+++ b/src/compiler/csharp_generator.cc
## -44,7 +44,7 ##
using google::protobuf::compiler::csharp::GetFileNamespace;
using google::protobuf::compiler::csharp::GetClassName;
-using google::protobuf::compiler::csharp::GetUmbrellaClassName;
+using google::protobuf::compiler::csharp::GetReflectionClassName;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::Descriptor;
using grpc::protobuf::ServiceDescriptor;
## -234,7 +234,7 ## void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se
out->Print("public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor\n");
out->Print("{\n");
out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n",
- "umbrella", GetUmbrellaClassName(service->file()), "index",
+ "umbrella", GetReflectionClassName(service->file()), "index",
index.str());
out->Print("}\n");
out->Print("\n");
More specifically, please open the file src/compiler/csharp_generator.cc and replace all references of GetUmbrellaClassName by GetReflectionClassName
Working backwards:
for release-0_11: it looks like you're trying to compile against the most recent protobuf. Since we're both in development right now there's occasional breakage - but grpc does track the version of protobuf it's tested against in third_party/protobuf. Try checking out and installing that version. I filed https://github.com/grpc/grpc/issues/4697 to update to the latest protobuf 3.0 version.
for master from github: which compiler and OS are you using? I recently checked in the boringssl integration work, so it's fresh, and not nearly as battle-tested. I'd like to get it battle-tested. That said, if you do a 'make EMBED_OPENSSL=false' then things should work out for you.
for the debian package problem: I'm not sure what's going on. I'm happy to try and spin up a VM with your OS and repro if you can let me know which OS it is.

bjam `Unable to find file or target named 'libboost_python'`

What am I missing in my Boost.Python configuration/installation?
I'm trying to compile tutorial example, and I get error with libboost_python not found
cd /usr/share/doc/libboost1.42-doc/examples/libs/python/example/tutorial
bjam
error: Unable to find file or target named
error: 'libboost_python'
error: referred from project at
error: '.'
But the library is there, ldconfig.real has been run:
/usr/lib/libboost_python.a -> libboost_python-py27.a
/usr/lib/libboost_python-mt-py26.a -> libboost_python-py26.a
/usr/lib/libboost_python-mt-py26.so -> libboost_python-py26.so.1.42.0
/usr/lib/libboost_python-mt-py27.a -> libboost_python-py27.a
/usr/lib/libboost_python-mt-py27.so -> libboost_python-py27.so.1.42.0
/usr/lib/libboost_python-py26.a
/usr/lib/libboost_python-py26.so -> libboost_python-py26.so.1.42.0
/usr/lib/libboost_python-py26.so.1.42.0
/usr/lib/libboost_python-py27.a
/usr/lib/libboost_python-py27.so -> libboost_python-py27.so.1.42.0
/usr/lib/libboost_python-py27.so.1.42.0
/usr/lib/libboost_python.so -> libboost_python-py27.so
I'm using default libboost packages from Ubuntu 11.04.
My user-config.jam is
using python : 2.7 ;
I had a similar problem on ubuntu 12.04 where I installed all the boost libraries as a package. I found the solution here:
http://jayrambhia.wordpress.com/2012/06/25/configuring-boostpython-and-hello-boost/
It turns out that you do not need to use bjam at all. A makefile suffices. I will repeat the the solution from the above link here:
1.) Install the libboost-python package
2.) Create a hello world source file called 'hello_ext.c':
char const* greet()
{
return "hello, world";
}
#include<boost/python.hpp>
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet",greet);
}
3.) Create a makefile:
PYTHON_VERSION = 2.7
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION)
# location of the Boost Python include files and library
BOOST_INC = /usr/include
BOOST_LIB = /usr/lib
# compile mesh classes
TARGET = hello_ext
$(TARGET).so: $(TARGET).o
g++ -shared -Wl,--export-dynamic $(TARGET).o -L$(BOOST_LIB) -lboost_python -L/usr /lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o $(TARGET).so
$(TARGET).o: $(TARGET).c
g++ -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c $(TARGET).c
4.) make
make
5.) Ready to use. In python:
import hello_ext
print hello_ext.greet()
Still not sure it that's the proper way, seems little hackish, but following helped:
In Jamroot file replaced
project
: requirements <library>libboost_python ;
with
project
: requirements <library>/usr/lib/libboost_python.so ;
You could have a site-config file with something like the following ;
using boost : 1.48 : <include>/usr/include/boost-1_48 <library>/usr/lib ;
(you need the < library > bit, not sure why)
then you can do stuff like.
project foo
: <library>/boost//python
Makes things easier in the long run, as you inevitably will have to change boost version at some point.

Categories

Resources