5 Stimmen

Wie rufe ich eine Python-Funktion von einem fremdsprachigen Thread (C++) auf?

Ich entwickle ein Programm, das DirectShow verwendet, um Audiodaten aus Mediendateien. DirectShow verwendet einen Thread, um Audiodaten an die Callback Funktion in meinem Programm zu übergeben, und ich lasse diese Callback-Funktion eine andere Funktion in Python aufrufen.

Ich verwende Boost.Python, um meine Bibliothek zu verpacken, die Callback-Funktion :

class PythonCallback {
private:
    object m_Function;
public:
    PythonCallback(object obj)
        : m_Function(obj)
    {}

    void operator() (double time, const AudioData &data) {
        // Call the callback function in python
        m_Function(time, data);
    }

};

Hier kommt das Problem, ein Thread von DirectShow ruft meine PythonCallback, nämlich die Funktion in Python auf. Sobald er aufruft, wird mein Programm einfach abstürzen. Ich fand heraus, dass dies ein Threading-Problem sein sollte. Dann habe ich dieses Dokument gefunden:

http://docs.python.org/c-api/init.html

Es scheint, dass mein Programm nicht zu Python-Funktion von Thread aufrufen kann direkt aufrufen, weil es eine globale Interpreter-Sperre gibt. Die GIL von Python ist so komplex, dass ich keine Ahnung habe, wie sie funktioniert. Es tut mir leid, was ich tun kann ist zu fragen. Meine Frage ist. Was sollte ich tun, bevor und nachdem ich eine Python-Funktion aus Threads aufrufen?

Das kann folgendermaßen aussehen.

void operator() (double time, const AudioData &data) {
    // acquire lock
    m_Function(time, data);
    // release lock
}

Danke. Victor Lin.

6voto

Éric Malenfant Punkte 13670

Werfen Sie einen Blick auf PyGILState_Ensure()/PyGILState_Release(), aus PEP 311 http://www.python.org/dev/peps/pep-0311/

Hier ist ein Beispiel aus dem PEP selbst:

void SomeCFunction(void)
{
    /* ensure we hold the lock */
    PyGILState_STATE state = PyGILState_Ensure();
    /* Use the Python API */
    ...
    /* Restore the state of Python */
    PyGILState_Release(state);
}

1voto

Mr Fooz Punkte 102791

Der C++-Callback soll die Daten in eine Warteschlange stellen. Der Python-Code soll die Warteschlange abfragen, um die Daten zu extrahieren.

0 Stimmen

Danke für Ihre Antwort. Das könnte eine Lösung sein. Allerdings erfordert diese Lösung eine zusätzliche Kopieroperation für den Audiopuffer. Das könnte ein Leistungsproblem sein.

0 Stimmen

Es könnte möglich sein, etwas Speicher in Python zuzuweisen und dann den Zeiger an Ihren C++-Code zu übergeben, damit er die Daten direkt dorthin übertragen kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X