0

你能从struct *Chibi Scheme 的 C 函数的 out 参数中得到一个吗?

我试图struct archive_entry *从这个 C 函数中得到一个:

int archive_read_next_header(
    struct archive *archive,
    struct archive_entry **out_entry);

在 C 中,人们会这样做:

struct archive_entry *entry;
archive_read_next_header(archive, &entry);

我的赤壁 FFI 代码是:

(define-c-struct archive)

(define-c-struct archive_entry)

(define-c int
          archive-read-next-header
          (archive (result reference archive_entry)))

但它没有生成正确的 C 代码来获取archive_entry. 我认为reference使用是错误的。我也试过pointer ,但也没有用。

4

1 回答 1

0

不知道能不能直接做。

但是我可以通过在 C 中编写一个自定义的 thunk 函数来解决这个问题:

(c-declare "
struct archive_entry *my_archive_read(struct archive *a, int *out_errcode) {
    struct archive_entry *entry;
    int errcode;

    *out_errcode = errcode = archive_read_next_header(a, &entry);
    return (errcode == ARCHIVE_OK) ? entry : NULL;
}")

(define-c archive_entry my-archive-read (archive (result int)))

**所以关键是Scheme在这个版本中不需要处理任何双重间接( )。C 代码将双间接转换为 Scheme 的单间接,因此一切正常。

Scheme程序的示例用法:

(let ((archive (my-archive-open filename)))
  (disp "archive" archive)
  (let* ((return-values (my-archive-read archive))
         (entry (car return-values))
         (errcode (cadr return-values)))
    (display entry)
    (newline)))

我从chibi-sqlite3sqlite3_stmt *绑定中复制了该技术,他们面临类似的问题,必须从 out 参数中获取 a :

(c-declare
 "sqlite3_stmt* sqlite3_prepare_return(sqlite3* db, const char* sql, const int len) {
    sqlite3_stmt* stmt;
    char** err;
    return sqlite3_prepare_v2(db, sql, len, &stmt, NULL) != SQLITE_OK ? NULL : stmt;
  }
")

(define-c sqlite3_stmt (sqlite3-prepare "sqlite3_prepare_return") (sqlite3 string (value (string-length arg1) int)))
于 2019-04-05T10:22:37.753 回答