【问题标题】:Collapsing offsets of cstructs in the Racket FFI在 Racket FFI 中折叠 cstructs 的偏移量
【发布时间】:2017-10-29 00:23:37
【问题描述】:

我有一个大的 cstruct,中间有两个字段,用于描述列表大小和指向列表的指针:

(define-cstruct _context
  (...
   [size _uint]
   [lst _pointer]
   ...)

但是,要到达这个列表,我总是首先需要获取大小,然后将指针转换为给定大小的列表。显然我可以创建一个函数来做到这一点:

(define (convert-to-list size clst)
  ...)

但我认为我们可以做得更好。也就是说,我想让字段“感觉”它是一个球拍列表/向量,而不必不断地将它传递给convert-to-list。我们可以通过另一个define-cstruct 来实现大部分目标,假设我们这样做了:

(define _clist
  (let ()
    (define-cstruct _clist
      ([size _uint]
       [lst _pointer])
    (make-ctype _clist #f
      (lambda (v)
        (cblock->list (ptr-ref (clist-lst v) _pointer)
                      _pointer
                      (clist-count v))))))

现在我可以将这个新结构放回旧结构中:

(define-cstruct _context
  (...
   [lst _clist]
   ...))

问题在于 _clist 现在被读取为 C 数据类型,这意味着它尝试对这个新结构使用标准 C 偏移量,而不是“内联”数据,可以这么说。

有什么方法可以在让 Racket 使用填充的同时使用这种模式,就好像新 cstruct 是直接用外部 cstruct 编写的一样?

(显然我可以使用 Racket 的元编程来内联结构,但那是使用核选项,如果我不需要它,我想避免它。)

【问题讨论】:

    标签: c struct racket padding ffi


    【解决方案1】:

    是的,实际上有一种方法可以让内部 cstruct (_clist) 填充自身,就像它是内联定义的一样,方法是使用 define-cstruct 中的 #:alignment 关键字。

    只需给出内部结构#:alignment 1,它就会自行对齐而无需额外的填充。

    生成的代码应如下所示:

    (define _clist
      (let ()
        (define-cstruct _clist
          ([size _uint]
           [lst _pointer]
          #:alignment 1)
        (make-ctype _clist #f
          (lambda (v)
            (cblock->list (ptr-ref (clist-lst v) _pointer)
                          _pointer
                          (clist-count v))))))
    

    现在你可以在外部结构中使用你的 new ,就好像直接提供了一个带有长度的列表:

    (define-cstruct _context
      (...
       [lst _clist]
       ...))
    

    感谢 Matthew Flatt 帮助我得出这个答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-12
      相关资源
      最近更新 更多