Tipps zum Aufrufen von Python von C.

In vielen Artikeln wurde zusammengefasst, wie eine in C geschriebene Funktion von Python aus aufgerufen wird, aber ich war hauptsächlich davon abhängig, da es nur wenige Artikel gab, in denen ausführlich beschrieben wurde, wie eine Funktion von C nach Python aufgerufen wird. ・ Stellen Sie ein Memo zusammen.

Kommandozeilenargumente

Ein Fehler tritt auf, wenn jemand versucht, auf ein Befehlszeilenargument zu verweisen. Wenn Sie in den obigen Fehler geraten, definieren Sie ihn.

pytest.py


import sys
    if not hasattr(sys, 'argv'):
        sys.argv = ['']  #Fügen Sie hier bei Bedarf Befehlszeilenargumente hinzu

Python-Modul wird geladen

In C sind die Teile, die normalerweise ohne Kenntnis verwendet werden, wie z. B. die Handhabung von Referenzzählern, handgeschrieben.

callPy.c


#include <Python.h>

//Aktuelles Verzeichnis zum Pfad hinzufügen
void set_path() {
    PyObject *sys      = PyImport_ImportModule("sys");
    PyObject *sys_path = PyObject_GetAttrString(sys, "path");
    PyList_Append(sys_path, PyUnicode_DecodeFSDefault("."));
}

void main(){
    PyObject *pModule, *pFunc, *pName;
    Py_Initialize();
  set_path();
    pName = PyUnicode_DecodeFSDefault("pytest");//Dateiname
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);//Verwendete Referenzen verringern den Referenzzähler.
    if(pModule != NULL){
        pFunc = PyObject_GetAttrString(pModule, "pyMethod");//Funktionsname
    }
}

Wenn Sie die Python-Datei des Moduls neben die ausführbare Datei stellen, kann sie aus irgendeinem Grund nicht gelesen werden, und Sie müssen anscheinend den aktuellen Ordner zum Pfad hinzufügen.

Strukturdefinition

callpy.c


typedef struct{
    int val1;
    float val2;
    float val3;
    float val4;
} STRUCT2;
#define ARRAY_MAX 100
typedef struct{
    int structNo;
    STRUCT2 results[ARRAY_MAX];
} STRUCT1;

Wenn Sie eine C-Struktur wie die oben auf der Python-Seite definieren möchten, In Python wird es mit ctypes definiert.

pytest.py


class STRUCT2(Structure):
        _fields_ = [
            ('val1', c_int32),
            ('val2', c_float),
            ('val3', c_float),
            ('val4', c_float),
        ]
class STRUCT1(Structure):
        ARRAY_MAX = 100
        _fields_ = [
            ('dataNo', c_int32),
            ('dataArray', STRUCT2 * ARRAY_MAX)
        ]

Wenn es sich um ein Zeigerarray anstelle einer Arrayentität handelt, kann es wie unten gezeigt als Zeiger definiert werden.

POINTER(STRUCT2) * ARRAY_MAX

Ich bin unzufrieden damit, dass ich die Array-Länge als Anfangswert definieren muss, obwohl es Python ist. Gibt es eine Möglichkeit, es dynamisch zu definieren, wenn Sie von C aus anrufen?

Rufen Sie Python von C aus auf

callpy.c


PyObject *pValue; //Zeiger für Rückgabewert
Pyobject *pArgArray[3];//Nimm 3 Argumente
Pyobject *pArgs = PyTuple_New(3);//
//Konvertieren Sie den Wert jedes Arguments in den PyObject-Typ
pArg[0] = PyUnicode_FromString("hogehoge");//String
pArg[1] = PyLong_FromLong(1000);//Numerischer Wert,int
pArg[2] = PyFloat_FromDouble(0.998);//Schwimmende Fraktion
for(int i = 0; i < 3 ; i++){
   PyTuple_SetItem(pArgs, i, pArg[i]);//Legen Sie Argumente in der Argumentliste fest
}
pValue = PyObject_CallObject(pFunc, pArgs);

Wenn Sie eine Struktur oder ein mehrdimensionales Array an Python übergeben möchten

Wenn Sie beispielsweise ein 640 * 480 RGB-Rohbild übergeben möchten, verwenden Sie PyArray_SimpleNewFromData, um es zu einem Objekt vom Typ 3D-Array zu machen.

callpy.c


import_array();

npy_intp dims[3] = {480, 640, 3};
pArg = PyArray_SimpleNewFromData(3, dimensions, NPY_UINT8, image);

Rückgabewert auf C-Seite (Normalwerttyp oder Zeichenfolge)

Wenn es sich um einen Rückgabewert vom Typ PyObject handelt, kann er auf dieselbe Weise wie eine Python-Funktion zurückgegeben werden. Natürlich sind mehrere Rückgabewerte in Ordnung

pytest.py


return val1, val2 #int, string

callpy.c


PyObject* pValue;
int num;
float decimal;
---Abkürzung---
pValue = PyObject_CallObject(pFunc, pArgs);
int result = PyArg_ParseTuple(pValue, "is", &num, &decimal);

Es gibt verschiedene Möglichkeiten, den Rückgabewert in C zu erhalten, aber ParseTuple scheint vorerst gut zu sein. Bestätigen das Format des Rückgabetyps im Voraus.

Rückgabewert auf C-Seite (Struktur oder Array von Strukturen)

Wenn es ein Typ vom Typ c wie C war, war ich süchtig nach Versuch und Irrtum und dachte, ich sollte nur den Zeiger von Python an C übergeben.

pytest.py


memoryview(mystruct).tobytes()

Wenn ich ein Byte-Array wie dieses erstellt habe, scheint es notwendig zu sein, es einmal zu einem PyObject-Typ zu machen, da es sich um einen Array-Typ von c-Typen handelt und nicht so wie er ist als C-Zeiger übergeben werden kann. Selbst wenn ich es als PyObject-Typ übergeben habe, wusste ich nicht, wie ich es mit c analysieren soll, also habe ich es implementiert, indem ich es mit dem Typ numpy.darray übergeben habe.

pytest.py


return np.frombuffer(struct, c_int8)

Konvertieren Sie die Struktur einfach direkt in den Darray-Typ mit numpy.frombuffer und empfangen Sie sie als numpy-Array mit C.

callpy.c


PyArrayObject *pArray;
PyArg_ParseTuple(pValue, "O", &pArray );
STRUCT1* struct_ptr = (STRUCT1*)PyArray_DATA(pArray);

Nach alldem

Anfangs wusste ich überhaupt nicht, wie man große Datenmengen übergibt, also habe ich verschiedene Dinge ausprobiert, wie beispielsweise die Verwendung der Speicherzuordnung, aber am Ende scheint die Übergabe als Byte-Array mit numpy.darray am schnellsten und am einfachsten zu verstehen zu sein. ..

Recommended Posts

Tipps zum Aufrufen von Python von C.
Hinweis für Pyjulia, die Julia aus Python anruft
Wickeln Sie C mit Cython für Python ein
~ Tipps für Python-Anfänger mit Liebe von Pythonista ① ~
Wrap C ++ mit Cython zur Verwendung von Python
~ Tipps für Python-Anfänger mit Liebe von Pythonista ② ~
Tipps für Python-Anfänger, um das Scikit-Image-Beispiel für sich selbst zu verwenden 9 Verwendung aus der C-Sprache
[Python + Selen] Tipps zum Scraping
~ Tipps für Python-Anfänger mit Liebe von Pythonista ③ ~
Python-Tipps
Rufen Sie popcount von Ruby / Python / C # auf
Python-Spickzettel (für C ++ erfahren)
[TouchDesigner] Tipps für die Anweisung von Python
Führen Sie Python-Code über die C # -GUI aus
Führen Sie Python-Skripte synchron von C # aus
Rufen Sie C / C ++ von Python auf dem Mac auf
Python-Tipps
Python-Tipps
Rufen Sie die c-Sprache von Python aus auf (python.h)
"Python AI Programmierung" ab 0 für Windows
Tipps zum Umgang mit Binärdateien in Python
Tipps zur Verwendung von Python + Caffe mit TSUBAME
Versuchen Sie, Python von Ruby aus mit Sparsamkeit aufzurufen
Python> Ausgaben von 1 bis 100, 501 bis 600> Für CSV
Generieren Sie mit Python eine C-Sprache aus dem S-Ausdruck
Tipps zum Erstellen kleiner Werkzeuge mit Python
Verwenden von C ++ - Funktionen aus Python mit pybind11
Eine Einführung in Python für C-Sprachprogrammierer
2016-10-30 sonst für Python3> für:
Python Conda Tipps
Python [für mich]
Tipps zum Bearbeiten von numpy.ndarray aus c ++ - Ich möchte einen Iterator verwenden -
Python-Klick-Tipps
SQL zu SQL
Unerwartet (?) Python Bean Wissen
Python C ++ Notizen
Python, openFrameworks (c ++)
Führen Sie Python-Skripte in C # -GUI-Anwendungen aus
Erstellen Sie ein C-Array aus einer Python> Excel-Tabelle
Ein Memorandum zum Aufrufen von Python aus Common Lisp
Tipps zum Erreichen der ATND-API mit Python
Boost.NumPy Tutorial zum Erweitern von Python in C ++ (Übung)
Rufen Sie die Python-Bibliothek zur Textnormalisierung in MATLAB auf
Rufen Sie Python-Skripte aus Embedded Python in C ++ / C ++ auf
Ich möchte C ++ - Code aus Python-Code erstellen!
Rufen Sie Polly aus dem AWS SDK für Python auf
Hinweis für oct2py beim Aufrufen des Octave-Skripts aus Python
Über Python für Schleife
Verwenden Sie thingspeak aus Python
Berühren Sie MySQL in Python 3
Python- und Numpy-Tipps
Bedienen Sie Filemaker von Python aus
Python-Grundlagen ② für Anweisung
Verwenden Sie fließend Python
Python C / C ++ - Erweiterungsmusterzeiger
Greifen Sie über Python auf Bitcoind zu
Änderungen von Python 3.0 zu Python 3.5
Änderungen von Python 2 zu Python 3.0
C-Sprache, Java, Python-Benchmarks mit Primfaktorisierung
Python aus oder importieren
Verwenden Sie MySQL aus Python