Create a C wrapper using Boost.Python

Now that I can call a C function in Python, I'll write a note. There are several ways to create a C wrapper, but this time I chose Boost.Python.

Installation

I installed it referring to this article. The procedure is as follows. (Mac environment, Python 3.7)

1. Install Boost.Python with brew

brew install boost-python3

2. Symbolic link

Once installed, link to the directory that runs Boost.Python's dylib and Python itself in / usr / local / Cellar /.

ln -s /usr/local/Cellar/boost-python3/1.71.0_1/lib/libboost_python37.dylib /path/to/directory/libboost_python37.dylib
ln -s /usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/Python /path/to/directory/libpython3.7.dylib

3. What to do if you get an error if pyconfig.h cannot be included

When first compiled I got a fatal error: pyconfig.h: No such file or directory, so I was able to solve it by following the steps below.

(1) Check the path of Python includes

python3.7-config --includes --libs

(2) The following information will appear. Choose the first (this example is -I / usr / local / Cellar / python / 3.7.5 / Frameworks / Python.framework / Versions / 3.7 / include / python3.7m)

-I/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/include/python3.7m -I/home/victor/anaconda3/include/python3.7m -lpython3.7m -lpthread -ldl -lutil -lrt -lm

(3) Add the following line to ~ / .bashrc with the path excluding -I:

~/.bashrc


export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/include/python3.7m"

(4) Reflect

source ~/.bashrc

Hello World Boost.Python is a C ++ library, so when using C, prepare C ++ separately and include the contents of C. Prepare C, C ++, Python files and Makefile:

my_c.h


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void hello_world();

my_c.c


#include "my_c.h"

void hello_world() {
  printf("hello world\n");
}

my_cpp.cpp


#include <boost/python.hpp>
extern "C" {
  #include "my_c.h"
}
using namespace boost::python;

BOOST_PYTHON_MODULE(my_wrapper){
    def("hello_world", hello_world);
}

my_python.py


import my_wrapper

my_wrapper.hello_world()

Makefile


wrapper: my_cpp.cpp
  gcc -c -o my_c.o my_c.c
  g++ -c -o my_cpp.o my_cpp.cpp
  g++ -fPIC -Wall -O2 -shared -o my_wrapper.so my_c.o my_cpp.o libboost_python37.dylib libpython3.7.dylib

You can do it with this

$ make
$ python my_python.py
hello world

Conversion of C struct and array to Python dict and list

If it is a simple function, no other processing is required, but if it is a type that does not know each other, conversion seems necessary. It will be sample code instead of explanation.

my_c.h


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
  int a;
  int b;
}my_struct;

my_struct my_sum(my_struct *my_array, int len);

my_c.c


#include "my_c.h"

my_struct my_sum(my_struct *my_array, int len) {
  my_struct sum = { 0 };
  for(int i = 0; i < len; i++) {
    sum.a += my_array[i].a;
    sum.b += my_array[i].b;
  }
  return sum;
}

my_cpp.cpp


#include <boost/python.hpp>
extern "C" {
  #include "my_c.h"
}
using namespace boost::python;

// boost::python::dict, boost::python::list, boost::python::len etc.
dict wrapper_sum(list py_list) {
  int length = len(py_list);
  my_struct ms[length];
  for(int i = 0; i < length; i++) {
    dict py_dict = extract<dict>(py_list[i]);
    ms[i].a = extract<int>(py_dict["a"]);
    ms[i].b = extract<int>(py_dict["b"]);
  }
  dict py_res;
  my_struct c_res = my_sum(ms, length);
  py_res["a"] = c_res.a;
  py_res["b"] = c_res.b;
  return py_res;
}

BOOST_PYTHON_MODULE(my_wrapper){
    def("my_sum", wrapper_sum);
}

my_python.py


import my_wrapper

data = [
    {
        "a": 3,
        "b": 9
    },
    {
        "a": 1,
        "b": 3
    },
    {
        "a": 6,
        "b": 2
    },
    {
        "a": 0,
        "b": 4
    }
]

res = my_wrapper.my_sum(data)
print(res)

I will do it:

$ make
$ python my_python.py
{'a': 10, 'b': 18}

Conclusion

With a little ingenuity, the function written in C for speed is I was very happy to be able to use it without rewriting it in Python.

Recommended Posts

Create a C wrapper using Boost.Python
Create a python GUI using tkinter
Create a nested dictionary using defaultdict
Create a CRUD API using FastAPI
Execute Python code on C ++ (using Boost.Python)
Create a graph using the Sympy module
[Python] Create a Batch environment using AWS-CDK
Create a dataframe from excel using pandas
Create a C array from a Python> Excel sheet
Create a beauty pageant support app using PyLearn2
Let's create a REST API using SpringBoot + MongoDB
Create a phylogenetic tree from Biopyton using ClustalW2
Create a binary data parser using Kaitai Struct
Create a web map using Python and GDAL
Create a Mac app using py2app and Python3! !!
Create a GUI on the terminal using curses
Create a Django schedule
Create a data collection bot in Python using Selenium
Create a color sensor using a Raspberry Pi and a camera
Create a Python module
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 1 ~
[Python] Create a ValueObject with a complete constructor using dataclasses
Create a pseudo REST API server using GitHub Pages
Type-aware using c ++ templates
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 2 ~
Create a Python environment
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 4 ~
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 5 ~
Create a dictionary by searching the table using sqlalchemy
Create a slack bot
Instantly create a diagram of 2D data using python's matplotlib
Let's create a function for parametrized test using frame object
Create a shogi game record management app using Django 4 ~ Create View ~
Create a game to control puzzle & dragons drops using pygame
Create a real-time auto-reply bot using the Twitter Streaming API
Create a gadget-like transparent background image type window using wxpython
Create a simple CRUD app using Django's generic class view
Using X11 with ubuntu18.04 (C)
Create a Wox plugin (Python)
Create a local pypi repository
Create a function in Python
Create a dictionary in Python
Create "Typoglycemia" sentences using COTOHA
Time measurement using a clock
Create a (simple) REST server
ABC129 A, B, C commentary
Create a homepage with django
Pepper Tutorial (5): Using a Tablet
Create a python numpy array
Using a printer with Debian 10
Create a dummy data file
Create a Django login screen
Create a simple textlint server
Create a directory with python
A memorandum of using eigen3
Create a rudimentary ELF packer
[C language] [Linux] Try to create a simple Linux command * Just add! !!
Create an API that returns data from a model using turicreate
Create a shogi game record management app using Django 2-Database settings-
Create a shogi game record management app using Django 6 ~ Template division ~
Create and deploy a Django (PTVS) app using Azure Table storage