Erstellen Sie mit Boost.Python einen C-Sprach-Wrapper

Ich konnte eine C-Funktion in Python aufrufen, also werde ich eine Notiz schreiben. Es gibt verschiedene Möglichkeiten, einen C-Wrapper zu erstellen, aber dieses Mal habe ich Boost.Python ausgewählt.

Installation

Ich habe es unter Bezugnahme auf [diesen Artikel] installiert (https://qiita.com/milmilk/items/f1d08cd2c3c72ebadb17). Das Verfahren ist wie folgt. (Mac-Umgebung, Python 3.7)

1. Installieren Sie Boost.Python mit Brew

brew install boost-python3

2. Symbolische Verknüpfung

Nach der Installation verknüpfen Sie das Verzeichnis, in dem Boost.Pythons Dylib und Python selbst ausgeführt werden, 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. Was tun, wenn eine Fehlermeldung angezeigt wird, wenn pyconfig.h nicht enthalten sein kann?

Beim ersten Kompilieren Ich habe einen schwerwiegenden Fehler erhalten: pyconfig.h: Keine solche Datei oder kein solches Verzeichnis. Daher konnte ich ihn beheben, indem ich die folgenden Schritte ausführte.

(1) Überprüfen Sie den Pfad der Python-Includes

python3.7-config --includes --libs

(2) Die folgenden Informationen werden angezeigt. Wählen Sie die erste aus (dieses Beispiel lautet "-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) Fügen Sie die folgende Zeile zu "~ / .bashrc" hinzu, wobei der Pfad "-I" ausschließt:

~/.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) Reflektieren

source ~/.bashrc

Hello World Boost.Python ist eine C ++ - Bibliothek. Wenn Sie also C verwenden, bereiten Sie C ++ separat vor und fügen Sie den Inhalt von C hinzu. Bereiten Sie C-, C ++ -, Python-Dateien und Makefile vor:

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

Sie können es damit machen

$ make
$ python my_python.py
hello world

Konvertierung von C struct und array in Python dict und list

Wenn es sich um eine einfache Funktion handelt, ist keine weitere Verarbeitung erforderlich. Wenn es sich jedoch um einen Typ handelt, der sich nicht kennt, erscheint eine Konvertierung erforderlich. Es wird ein Beispielcode anstelle einer Erklärung sein.

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)

Ich werde das machen:

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

Fazit

Mit ein wenig Einfallsreichtum ist die in C für Geschwindigkeit geschriebene Funktion Ich war sehr froh, es verwenden zu können, ohne es in Python neu zu schreiben.

Recommended Posts

Erstellen Sie mit Boost.Python einen C-Sprach-Wrapper
Erstellen Sie mit tkinter eine Python-GUI
Erstellen Sie ein verschachteltes Wörterbuch mit defaultdict
Erstellen Sie die CRUD-API mit der Fast API
Führen Sie Python-Code unter C ++ aus (mit Boost.Python).
Erstellen Sie mit dem Sympy-Modul ein Diagramm
[Python] Erstellen Sie eine Stapelumgebung mit AWS-CDK
Erstellen Sie mit Pandas einen Datenrahmen aus Excel
Erstellen Sie ein C-Array aus einer Python> Excel-Tabelle
Erstellen Sie mit PyLearn2 eine App zur falschen Unterstützung
Erstellen wir eine REST-API mit SpringBoot + MongoDB
Erstellen Sie mit ClustalW2 einen phylogenetischen Baum aus Biopyton
Erstellen Sie mit Kaitai Struct einen Binärdatenparser
Erstellen Sie eine Webmap mit Python und GDAL
Erstellen Sie eine GUI auf dem Terminal mit Flüchen
Erstellen Sie einen Django-Zeitplan
Erstellen Sie mit Selenium einen Datenerfassungsbot in Python
Erstellen Sie einen Farbsensor mit einem Raspeltorte und einer Kamera
Erstellen Sie ein Python-Modul
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 1 ~
[Python] Generieren Sie ValueObject mit dem vollständigen Konstruktor mithilfe von Datenklassen
Erstellen Sie mit GitHub Pages einen Pseudo-REST-API-Server
Typunabhängig mit C ++ - Vorlagen
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 2 ~
Erstellen Sie eine Python-Umgebung
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 4 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 5 ~
Durchsuchen Sie die Tabelle mit sqlalchemy und erstellen Sie ein Wörterbuch
Erstellen Sie einen Slack Bot
Erstellen Sie sofort ein Diagramm mit 2D-Daten mit der matplotlib von Python
Erstellen wir eine Funktion für den parametrisierten Test mithilfe eines Rahmenobjekts
Erstellen Sie eine Shogi Score Management App mit Django 4 ~ Create View ~
Ich werde ein Spiel machen, um das Ablegen von Rätseln und Drachen mithilfe von Pygame zu kontrollieren
Erstellen Sie mithilfe der Twitter-Streaming-API einen Echtzeit-Bot für die automatische Antwort
Verwenden Sie wxpython, um ein Gadget-ähnliches transparentes Hintergrundbildfenster zu erstellen
Erstellen Sie eine einfache CRUD-App mit der generischen Klassenansicht von Django
Verwenden von X11 mit ubuntu18.04 (C-Sprache)
Erstellen Sie ein Wox-Plugin (Python)
Erstellen Sie eine Funktion in Python
Erstellen Sie ein Wörterbuch in Python
Erstellen Sie mit COTOHA "Typogrisemia" -Sätze
Zeitmessung mit einer Uhr
Erstellen Sie einen (einfachen) REST-Server
ABC129 A, B, C Kommentar
Erstellen Sie eine Homepage mit Django
Pfeffer-Tutorial (5): Verwenden eines Tablets
Erstellen Sie ein Python-Numpy-Array
Verwenden eines Druckers mit Debian 10
Erstellen Sie eine Dummy-Datendatei
Erstellen Sie einen Django-Anmeldebildschirm
Erstellen Sie einen einfachen Textlint-Server
Erstellen Sie ein Verzeichnis mit Python
Ein Memorandum zur Verwendung von eigen3
Erstellen Sie einen rudimentären ELF-Packer
[C-Sprache] [Linux] Versuchen Sie, einen einfachen Linux-Befehl zu erstellen. * Fügen Sie einfach hinzu! !!
Erstellen Sie mit turicreate eine API, die Daten aus einem Modell zurückgibt
Erstellen Sie eine Shogi Score Management App mit Django 2 ~ Datenbankeinstellungen ~
Erstellen Sie eine Shogi Score Management App mit Django 6 ~ Split Template ~
Erstellen und Bereitstellen von Django-Apps (PTVS) mithilfe des Azure Table-Speichers