boost.python 1

background

in OEM’s ADS team, there are bunch of model-based design engineers, who build the ADAS features based on Matlab/Simulink tools, which is good to build quick demos, when comes to massive data verification, we can’t really depends on Matlab solver, which is so slow and licensed.

so a common idea is to recompile the Matlab/Simulink model to C/C++ code, which can further embedded to more open envs, e.g. python or C++.

as previously mentioned, we had designed a rq based massive data driven test framework, so the gap from C++ ADAS code to this python test framework is fixed in this blog.

there are a few wasy to integrate C++ code to Python, one is Boost.Python:

setup

install boost

configuring Boost.BUild

python env : 3.6 (from conda env aeb)
gcc: 4.5.0

1
export BOOST_BUILD_PATH=`pwd` #where we keep `user-config.jam`

user-config.jam

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using gcc : 5.4.0 : /usr/bin/g++ ;
using python : 3.6
: "/home/anaconda3/envs/aeb/bin/python"
: "/home/anaconda3/envs/aeb/include"
: "/home/anaconda3/envs/aeb/include/python3.6m" ;
```
bootstrap will find `user-config.jam` from $BOOST_BUILD_PATH.
```sh
cd /path/to/boost_1_73_0
./bootstrap.sh --help
./bootstrap.sh --prefix=/usr/local/ --show-libraries
b2 --with-python --prefix="/usr/local/" install variant=release link=static address-model=64
b2 --clean

a sample of user-config.jam

  • error fixing
1
2
fatal error: pyconfig.h: No such file or directory
compilation terminated.

need export CPATH=~/anaconda/envs/aeb/include/python3.6m/, where located pyconfig.h and other headers

finally report: boost.python build successfully !

demo run

the following is simple sample of how to use boost_python wrapper to wrapping an AEB model(in c++) to python

aeb.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
typedef struct {
float time;
float dx ;
float dy ;
} AEB;
typedef struct {
AEB out1 ;
} OP;
class aeb {
public:
Student() {}
OP op_out ;
void test_op(){
(void) memset((void *)&op_out, 0, sizeof(OP));
op_out.out1.time = 1.0 ;
op_out.out1.dx = 2.0 ;
op_out.out1.dy = 3.0 ;
AEB o1 = op_out.out1 ;
std::cout << o1.time << std::endl ;
}
};

wrap_aeb.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <Python.h>
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "aeb.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(aeb) {
scope().attr("__version__") = "1.0.0";
scope().attr("__doc__") = "a demo module to use boost_python.";
class_<aeb>("aeb", "a class of aeb")
.def(init<>())
.def("test_op", &aeb::test_op, "test op")
.def_readonly("op_out", &aeb::op_out)
}
```
tips, if aeb.h and aeb.cpp are separated files, it's better to merge them first; for nested structure in wrapper is another topic later.
#### build and python import
* check header location
Python.h @ `/home/anaconda3/envs/aeb/include/python3.6m`
boost/python @ `/usr/local/include/boost`
* check .so lib location
/usr/local/lib/
tips, if there is duplicated `boost lib` in system, e.g. `/usr/lib/x86_64-linxu-gnu/libboost_python.so` which maybe conflict with `boost_python` install location at `/usr/local/lib/libboost_python36.so`
* build
```sh
g++ -I/home/anaconda3/envs/aeb/include/python3.6m -I/usr/local/include/boost -fPIC wrap_aeb.cpp -L/usr/local/lib/ -lboost_python36 -shared -o aeb.so
  • test
1
2
3
import aeb
t = aeb.aeb
t.test_op()

summary

this blog gives the basic idea how to use boost.python to integrate c++ to python test framework. there are plenty details need fixed, e.g. nested structures, share_pointers. maybe share in next blog.

refere

boost.python tutorial