1

スキームの FFI を使用して libpython へのバインディングを作成しようとしています。これを行うには、python の場所を取得して を作成しffi-lib、そこから関数を作成する必要があります。たとえば、私はこれを行うことができます:

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

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

これで問題ありませんが、関数をエクスポートする方法が思い浮かびません。たとえば、次のようなことができます。

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

...しかし、どうにかして libpython (link-python によって作成された) への参照をグローバルに保存する必要があります。link-python が呼び出されたら、これらの関数をエクスポートする方法はありますか? 言い換えれば、モジュールを使用している誰かがこれを行うことができるようにしたいと思います:

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

...またはこれ:

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

...しかし、これでエラーが発生します:

(require pyscheme)
(Py_Initialize)

これどうやってするの?

4

3 に答える 3

2

おそらく、このようなことを行う最も簡単な方法は、必要になるまでバインディングを遅らせることです。この(テストされていない)コードのようなもの:

#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"))

関数自体の内部で設定を行うことができるので、決して呼び出されない関数をバインドしません。

#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")))

すべての関数に対してこれを行う必要はないため、マクロでラップする必要があります。

#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...

ただし、2 つの大まかな注意事項:

  • 可能ではありますが、このように物事を遅らせるのは醜いようです。コードの開始時に既知の環境変数を使用したいと思います。

  • 過去にplt スキームを pythonにリンクする試みがありましたが、メモリの問題を扱う IIRC は快適ではありませんでした。(ただし、これは現在の外国のシステムが導入される前の話です。)

于 2010-05-28T18:46:58.483 に答える
0

私は多くのモジュールを作成していませんが、新しい名前空間にロードしたい関数を「提供」する必要があると思います。

(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)
于 2010-05-27T20:45:49.047 に答える
0

libpythonCMake は自動的にパスを見つけることができます:

find_package( PythonLibs 3.3 REQUIRED )

詳細な例はこちら

次に、リンクされたシャード ライブラリを使用できます。例: https://github.com/niitsuma/pyjsonrpcembd

于 2014-08-23T02:31:48.790 に答える