Créez un wrapper de langage C à l'aide de Boost.Python

J'ai pu appeler une fonction C en Python, donc j'écrirai une note. Il existe plusieurs façons de créer un wrapper C, mais cette fois j'ai choisi Boost.Python.

Installation

Je l'ai installé en référence à cet article. La procédure est la suivante. (Environnement Mac, Python 3.7)

1. Installez Boost.Python avec brew

brew install boost-python3

2. Lien symbolique

Une fois installé, créez un lien vers le répertoire qui exécute le dylib de Boost.Python et Python lui-même dans / 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. Que faire si vous obtenez une erreur si pyconfig.h ne peut pas être inclus

Lors de la première compilation J'ai eu une erreur fatale: pyconfig.h: aucun fichier ou répertoire de ce type, j'ai donc pu le résoudre en suivant les étapes ci-dessous.

(1) Vérifiez le chemin de Python comprend

python3.7-config --includes --libs

(2) Les informations suivantes s'affichent. Choisissez le premier (cet exemple est -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) Ajoutez la ligne suivante à ~ / .bashrc avec le chemin excluant -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) Réfléchir

source ~/.bashrc

Hello World Boost.Python est une bibliothèque C ++, donc lorsque vous utilisez C, préparez C ++ séparément et incluez le contenu de C. Préparez les fichiers C, C ++, Python et 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

Tu peux le faire avec ça

$ make
$ python my_python.py
hello world

Conversion de la structure et du tableau C en dict et liste Python

S'il s'agit d'une fonction simple, aucun autre traitement n'est requis, mais s'il s'agit d'un type qui ne se connaît pas, la conversion semble nécessaire. Ce sera un exemple de code au lieu d'explication.

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)

Je le ferai:

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

Conclusion

Avec un peu d'ingéniosité, la fonction écrite en C pour la vitesse est J'étais très heureux de pouvoir l'utiliser sans le réécrire en Python.

Recommended Posts

Créez un wrapper de langage C à l'aide de Boost.Python
Créer une interface graphique python à l'aide de tkinter
Créer un dictionnaire imbriqué à l'aide de defaultdict
Créer une API CRUD à l'aide de l'API rapide
Exécuter du code Python sur C ++ (en utilisant Boost.Python)
Créer un graphique à l'aide du module Sympy
[Python] Créer un environnement Batch à l'aide d'AWS-CDK
Créer un bloc de données à partir d'Excel à l'aide de pandas
Créer un tableau C à partir d'une feuille Python> Excel
Créer une application d'assistance technique à l'aide de PyLearn2
Créons une API REST en utilisant SpringBoot + MongoDB
Créer un arbre phylogénétique à partir de Biopyton en utilisant ClustalW2
Créer un analyseur de données binaires à l'aide de Kaitai Struct
Créer une carte Web en utilisant Python et GDAL
Créez une interface graphique sur le terminal à l'aide de curses
Créer un planning Django
Créer un bot de collecte de données en Python à l'aide de Selenium
Créez un capteur de couleur à l'aide d'une tarte à la râpe et d'une caméra
Créer un module Python
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 1 ~
[Python] Générer ValueObject avec un constructeur complet à l'aide de classes de données
Créer un pseudo serveur d'API REST à l'aide de pages GitHub
Indépendant du type à l'aide de modèles C ++
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 2 ~
Créer un environnement Python
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 4 ~
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 5 ~
Rechercher la table à l'aide de sqlalchemy et créer un dictionnaire
Créer un bot slack
Créez instantanément un diagramme de données 2D à l'aide de matplotlib de python
Créons une fonction pour le test paramétré à l'aide d'un objet frame
Créez une application de gestion de partition shogi à l'aide de Django 4 ~ Créer une vue ~
Je vais créer un jeu pour contrôler le puzzle et les dragons en utilisant pygame
Créez un robot de réponse automatique en temps réel à l'aide de l'API Twitter Streaming
Utilisez wxpython pour créer une fenêtre de type d'image d'arrière-plan transparent semblable à un gadget
Créez une application CRUD simple en utilisant la vue de classe générique de Django
Utilisation de X11 avec ubuntu18.04 (langage C)
Créer un plugin Wox (Python)
Créer un référentiel pypi local
Créer une fonction en Python
Créer un dictionnaire en Python
Créez des phrases "Typogrisemia" en utilisant COTOHA
Mesure du temps à l'aide d'une horloge
Créer un serveur REST (simple)
ABC129 Commentaire A, B, C
Créer une page d'accueil avec django
Tutoriel Pepper (5): Utilisation d'une tablette
Créer un tableau numpy python
Utiliser une imprimante avec Debian 10
Créer un fichier de données factice
Créer un écran de connexion Django
Créer un serveur textlint simple
Créer un répertoire avec python
Un mémorandum d'utilisation de eigen3
Créer un packer ELF rudimentaire
[Langage C] [Linux] Essayez de créer une simple commande Linux * Ajoutez simplement! !!
Créer une API qui renvoie les données d'un modèle à l'aide de turicreate
Créez une application de gestion de score shogi à l'aide de Django 2 ~ Paramètres de la base de données ~
Créez une application de gestion de partition shogi à l'aide de Django 6 ~ Split Template ~
Création et déploiement d'applications Django (PTVS) à l'aide du stockage Azure Table