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.
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)
brew install boost-python3
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
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
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}
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