Racket FFI:将指针初始化为NULL

时间:2014-09-09 11:16:31

标签: racket ffi

这是我第一次尝试使用Racket的FFI。我想创建一个绑定到libgit2的应用程序,以便操作GIT存储库。

我需要做的第一件事是初始化存储库as shown in the libgit2 documentation

git_repository *repo = NULL;
int error = git_repository_init(&repo, "/tmp/…", false);

在Racket中获取函数调用非常简单:

(require ffi/unsafe
         ffi/unsafe/define)
(define-ffi-definer define-libgit (ffi-lib "/opt/local/lib/libgit2.dylib"))
(define _git_repository-ptr (_cpointer/null 'git_repository))
(define-libgit git_repository_init (_fun _git_repository-ptr _string _bool -> _int))

但是然后尝试使用该功能不起作用:

-> (define new_repo _git_repository-ptr)
-> (git_repository_init new_repo "/tmp/..." #f)
; git_repository->C: argument is not `git_repository' pointer
;   argument: #<ctype>
; [,bt for context]

libgit2不提供初始化指针的函数as shown in the Racket FFI documentation example

这是定义可空指针并将其初始化为NULL的正确方法吗?

另一方面,

git_repository是库中定义的struct。我是否应该在Racket端使用define-cstruct来正确使用它?这可能很麻烦,因为struct是根据其他struct来定义的,具有一定程度的嵌套。有没有处理这种情况的模式?

1 个答案:

答案 0 :(得分:7)

问题不在于指针未初始化为null;事实上,git_repository_init文档并没有说它必须初始化为任何东西。问题是它是一个out参数,而你的函数声明没有指定。

这是我测试的一些代码(在Ubuntu 14.04上),对我有用:

> (require ffi/unsafe ffi/unsafe/define) 
> (define-ffi-definer define-libgit (ffi-lib "libgit2"))
> (define _git_repository-ptr (_cpointer/null 'git_repository)) 
> (define-libgit git_repository_init (_fun (repo : (_ptr o _git_repository-ptr)) _string _bool -> (rc : _int) -> (values repo rc)))
> (git_repository_init "/tmp/repo" #f)
#<cpointer:git_repository>
0

有关如何指定out参数的信息,请参阅_ptr的文档。 (您也可以使用它来指定输入/输出参数,但这些通常很少见。)

(当然,你最终会想按摩你的FFI,而不是像我的例子中那样返回两个值,而是简单地检查错误的返回代码,并在适当时引发适当的Racket错误,以及如果成功则返回存储库指针。)