In Racket kann ich Funktionen exportieren nach dem anderen Funktion aufgerufen wurde?

StackOverflow https://stackoverflow.com/questions/2923909

  •  05-10-2019
  •  | 
  •  

Frage

Ich versuche, eine Bindung an libpython mit Schema des FFI zu erstellen. Um dies zu tun, muss ich die Lage von Python bekommen, erstellen Sie die ffi-lib, und erstellen Sie dann Funktionen von ihm. So zum Beispiel könnte ich dies tun:

(module pyscheme scheme
  (require foreign)
  (unsafe!)

  (define (link-python [lib "/usr/lib/libpython2.6.so"])
    (ffi-lib lib))

Das ist alles schön und gut, aber ich kann einen Weg zu Exportfunktionen nicht denken. Zum Beispiel könnte ich so etwas tun:

(define Py_Initialize (get-ffi-obj "Py_Initialize" libpython (_fun -> _void)))

... aber dann würde ich einen Verweis auf libpython speichern muß (erstellt von Link-Python) global irgendwie. Gibt es eine Möglichkeit, diese Funktionen zu exportieren, wenn Link-Python genannt wird? Mit anderen Worten, ich möchte jemand das Modul mit diesen in der Lage sein zu tun:

(require pyscheme)
(link-python)
(Py_Initialize)

... oder so:

(require pyscheme)
(link-python "/weird/location/for/libpython.so")
(Py_Initialize)

... aber haben diese geben einen Fehler:

(require pyscheme)
(Py_Initialize)

Wie kann ich das tun?

War es hilfreich?

Lösung

Wahrscheinlich der einfachste Weg, um so etwas zu tun ist, um die Bindung zu verzögern, bis sie gebraucht wird. So etwas wie dieser (ungetestet) Code:

#lang scheme

(require scheme/foreign)
(unsafe!)

(define libpython #f)

(define (link-python [lib "/usr/lib/libpython2.6.so"])
  (if libpython
    (error "Foo!")
    (begin (set! libpython (ffi-lib lib))
           (set! Py_Initialize
                 (get-ffi-obj "Py_Initialize" libpython
                              (_fun -> _void))))))

(define (Py_Initialize . args)
  (error 'Py_Initialize "python not linked yet"))

Ir können Sie die Einstellung innerhalb der Funktion tun selbst, so dass Sie nicht binden Funktionen tun, die nie aufgerufen werden:

#lang scheme

(require scheme/foreign)
(unsafe!)

(define libpython #f)

(define (link-python [lib "/usr/lib/libpython2.6.so"])
  (if libpython (error "Foo!") (set! libpython (ffi-lib lib))))

(define (Py_Initialize . args)
  (if libpython
    (begin (set! Py_Initialize
                 (get-ffi-obj "Py_Initialize" libpython
                              (_fun -> _void)))
           (apply Py_Initialize args))
    (error 'Py_Initialize "python not linked yet")))

und da Sie nicht diese für jede einzelne Funktion tun wollen, sollten Sie es wickeln in einem Makro:

#lang scheme

(require scheme/foreign)
(unsafe!)

(define libpython #f)

(define (link-python [lib "/usr/lib/libpython2.6.so"])
  (if libpython (error "Foo!") (set! libpython (ffi-lib lib))))

(define-syntax-rule (defpython <name> type)
  (define (<name> . args)
    (if libpython
      (begin (set! <name> (get-ffi-obj '<name> libpython <type>))
             (apply <name> args))
      (error '<name> "python not linked yet"))))

(defpython Py_Initialize (_fun -> _void))
(defpython Py_Foo (_fun _int _int -> _whatever))
...more...

Aber zwei High-Level-Hinweise:

  • Auch wenn es möglich ist, so scheint es hässlich Verzögerung Dinge auf diese Weise. Ich würde eher eine Umgebungsvariable verwenden, dass, wenn der Code beginnt bekannt ist.

  • Es gibt einen Versuch in der Vergangenheit Link gewesen PLT-Schema zu python und IIRC, war mit Speicherproblemen beschäftigen nicht angenehm. (Aber das ist, bevor wir das aktuelle fremde System an Ort und Stelle hatten.)

Andere Tipps

Ich habe nicht viele Module gemacht, aber ich glaube, Sie müssen zu ‚liefern‘, um die Funktionen, die Sie laden in den neuen Namensraum werden soll.

(module pyscheme scheme
  (provide
   link-python
   Py_Initialize
   <...>)
  (require foreign)
  (unsafe!)

  (define (link-python [lib "/usr/lib/libpython2.6.so"])
    (ffi-lib lib)))
(require pyscheme)
(link-python "/weird/location/for/libpython.so")
(Py_Initialize)

CMake automatisch libpython Pfad:

find_package( PythonLibs 3.3 REQUIRED )

Detailliertere Beispiel hier .

Dann können Sie einige verknüpfte Scherbe lib verwenden. Beispielsweise: https://github.com/niitsuma/pyjsonrpcembd

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top