折叠cstructs的偏移球拍FFI

问题描述:

我有一个在中间具有两个字段描述列表的大小和一个指向列表中的大cstruct:折叠cstructs的偏移球拍FFI

(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偏移量,而不是“内联”数据,可以这么说。

有没有什么办法让我可以使用这种模式,同时让球拍使用填充,就好像新的cstruct是直接用外部写入一样?

(很显然,我可以使用球拍的元编程内联结构,但正在使用的核选择,我想避免,如果我不需要它其中。)

是的,其实是一个通过使用define-cstruct中的#:alignment关键字来获取内部cstruct(_clist)以便将其自身填充,就好像它是内联定义的一样。

只需给内部结构#: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)))))) 

现在你可以使用新的外部结构仿佛一个长度列表直接提供:

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

谢谢马修弗拉特帮助我得出这个答案。