在 Racket 中,我可以在调用另一个函数后导出函数吗?

发布于 2024-09-03 09:30:34 字数 813 浏览 9 评论 0原文

我正在尝试使用方案的 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)

我该如何执行此操作?

I'm trying to create a binding to libpython using scheme's FFI. To do this, I have to get the location of python, create the ffi-lib, and then create functions from it. So for instance I could do this:

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

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

This is all well and good, but I can't think of a way to export functions. For instance, I could do something like this:

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

...but then I'd have to store a reference to libpython (created by link-python) globally somehow. Is there any way to export these functions once link-python is called? In other words, I'd like someone using the module to be able to do this:

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

...or this:

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

...but have this give an error:

(require pyscheme)
(Py_Initialize)

How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

假面具 2024-09-10 09:30:34

执行此类操作的最简单方法可能是延迟绑定,直到需要它们为止。像这样的(未经测试的)代码:

#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,处理内存问题并不令人愉快。 (但这是在我们建立当前的外国系统之前。)

Probably the easiest way to do something like this is to delay the binding until they're needed. Something like this (untested) 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 you can do the setting inside the function itself, so you don't bind functions that are never called:

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

and since you won't want to do this for every single function, you should wrap it in a macro:

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

But two highlevel notes:

  • Even though it's possible, it seems ugly to delay things this way. I'd rather use some environment variable that is known when the code starts.

  • There have been an attempt in the past to link plt scheme to python, and IIRC, dealing with memory issues was not pleasant. (But this is before we had the current foreign system in place.)

烟雨凡馨 2024-09-10 09:30:34

我没有制作很多模块,但我认为您需要“提供”要加载到新名称空间中的功能。

(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)

I have not made many modules, but I think you need to 'provide' the functions that you want to load into the new namespace.

(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)
小草泠泠 2024-09-10 09:30:34

CMake 可以自动查找 libpython 路径:

find_package( PythonLibs 3.3 REQUIRED )

更详细的示例 此处

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

CMake can automatically find libpython path:

find_package( PythonLibs 3.3 REQUIRED )

More detailed example here.

Then you can use some linked sherd lib.
For example:
https://github.com/niitsuma/pyjsonrpcembd

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文