Получить структуру * из параметра out в привязках Fibi Scheme Fibre Chibi
Вы можете получить struct *
из параметра out функции C в схеме Чиби?
Я пытаюсь получить struct archive_entry *
из этой функции C:
int archive_read_next_header(
struct archive *archive,
struct archive_entry **out_entry);
В Си это можно сделать так:
struct archive_entry *entry;
archive_read_next_header(archive, &entry);
Мой код Chibi 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
но это тоже не сработало.
1 ответ
Я до сих пор не знаю, можно ли это сделать напрямую.
Но я смог обойти эту проблему, написав пользовательскую функцию thunk на C:
(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)))
Таким образом, ключ заключается в том, что Схема не должна иметь дело с какой-либо двойной косвенности (**
) в этой версии. Код 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-sqlite3, где они сталкиваются с аналогичной проблемой, связанной с получением sqlite3_stmt *
из выходного параметра:
(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)))