首页 文章

在Racket中动态创建FFI方法

提问于
浏览
1

我正在尝试通过Racket中的FFI加载С/ Rust / etc功能 . 我想将函数名列表指定为字符串,然后通过一些辅助函数加载它们 . 主要问题是从字符串创建标识符/单词 . 例如,在Rebol中它非常简单:

foo: "test1"
set to-word (rejoin [foo "_result_data"]) some
print test1_result_data

但是在Racket中我必须使用语法东西 . 所以我找到了像How do I define functions using Racket macros?Racket Macro to auto-define functions given a list这样的例子 . 它们涵盖了我需要的很多知识,所以我写了下一个片段:

#lang racket
(require (for-syntax racket/syntax ffi/unsafe))

(define-for-syntax *method-names*
  ; Given I have hello, one and two methods in my shared lib
  (list "hello"
        "one"
        "two"
        ))

(define-syntax (define-ffi-func stx)
  (syntax-case stx ()
    [(_)
     (let ([elem->fn-id 
            (λ (elem-str)
              (format-id 
               stx "~a" 
               (datum->syntax stx (string->symbol elem-str))))]
            [rustlib
              (ffi-lib "/path/to/libffitest.dylib")
              ]
            )
       (with-syntax 
         ([((method cation) ...)
           (map 
            (λ (elem)
              ; I can load C code here for sure :) But not much more
              ; (define c (get-ffi-obj elem rustlib (_fun -> _int)
              ;  (lambda ()
              ;     (error 'rustlib
              ;      "installed lib does not provide given method"))))
              (list (elem->fn-id elem) elem)
            )
            *method-names*)])
         #`(begin
             (define (method) 
              ; I'm curious what should be here
                1
              )
             ...)))]))

(define-ffi-func)
; Actually one, two and hello methods are in scope
; but surely they all return 1
(two)

但是我仍然可以在 with-syntax 中匹配它们,但是进一步的语法定义对外部模块一无所知(例如

#`(begin
    (define (ate) 
        (get-ffi-obj elem rustlib (_fun -> _int))
         )
     ...)))]))

不管用 .

我想我也错过了关于绑定匹配的东西 .

如何通过指定名称列表来获得FFI绑定方法?提前致谢!

2 回答

  • 0

    既然你已经回答了你的主要问题,我只是想说一下,使用字符串列表来表示名称并不是一般的Rackety . 使用标识符通常更好 . 你真的需要动态计算这些字符串吗?

    如果不这样做,那么在给定标识符列表的情况下编写宏来定义所有FFI绑定非常简单:

    (define-syntax-rule (define-ffi-functions name ...)
      (begin (define name
               (get-ffi-obj (quote name) ffi-lib (_fun -> _int)))
             ...))
    
    (define-ffi-functions hello one two)
    

    合适的 ffi-lib 定义 .

  • 1

    终于结束了这样的事情:

    (define-for-syntax *method-names*
      (list "hello"
            "one"
            "two"
            ))
    
    (define rustlib (ffi-lib "/path/to/Projects/libffitest.dylib"))
    
    (define-syntax (define-ffi-func stx)
      (syntax-case stx ()
        [(_ lib ffi-func)
         (let ([elem->fn-id 
                (λ (elem-str)
                  (format-id 
                   stx "~a" 
                   (datum->syntax stx (string->symbol elem-str))))]
                )
           (with-syntax 
             ([((method name) ...)
               (map 
                (λ (elem)
                  (list (elem->fn-id elem) elem)
                )
                *method-names*)])
             #`(begin
                 (define method
                    (ffi-func name lib (_fun -> _int))
                  )
                 ...)))]))
    
    (define-ffi-func rustlib get-ffi-obj)
    (+ (one) (two))
    

    还需要抛光,但总的来说是可以理解的 .

相关问题