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

但是有两个高级说明:

  • 尽管有可能,但以这种方式拖延事情似乎很难看。我宁愿使用一些在代码启动时已知的环境变量。

  • 过去曾尝试将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

CMake 可以自动查找libpython路径:

find_package( PythonLibs 3.3 REQUIRED )

更详细的例子在这里

然后你可以使用一些链接的 Sherd 库。例如: https ://github.com/niitsuma/pyjsonrpcembd

于 2014-08-23T02:31:48.790 回答