我正在尝试使用scheme的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)
我该怎么做?
答案 0 :(得分: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 scheme to python与IIRC联系起来,处理记忆问题并不令人愉快。 (但这是在我们建立现有的外国系统之前。)
答案 1 :(得分: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)
答案 2 :(得分:0)
CMake可以自动找到libpython
路径:
find_package( PythonLibs 3.3 REQUIRED )
更详细的示例here。
然后你可以使用一些链接的sherd lib。 例如: https://github.com/niitsuma/pyjsonrpcembd