2017-05-28 55 views
2

我有一個在中間具有兩個字段描述列表的大小和一個指向列表中的大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是直接用外部寫入一樣?

(很顯然,我可以使用球拍的元編程內聯結構,但正在使用的核選擇,我想避免,如果我不需要它其中。)

回答

2

是的,其實是一個通過使用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] 
    ...)) 

謝謝馬修弗拉特幫助我得出這個答案。