在 Julia 中声明 C void 指针的正确方法
the proper way to declare C void pointers in Julia
好吧,我本来就把这个问题的提法搞砸了(我认真写C++代码已经一年多了,我对纯C的经验非常有限),所以让我们再试一次。
一些 C 代码被编写为期望您执行如下操作
void* p;
create_new_thing(&p); //p is now a new thing
do_stuff_to_thing(p); //something happened to p
我的问题是如何在 Julia 中创建对象 p
。现在我认为答案是
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p)
此外,我相信相同的代码但将 p
声明为 p = Array(Ptr{Void}, 1)
也有效。
然而,我确实发现 Julia 中 Ref
和 Ptr
之间的整个区别非常混乱,主要是因为它们似乎以我无法跟踪的方式相互转换。
您的代码看起来 几乎 不错。不过要小心!任何小错误,例如您在此处遇到的错误,都可能导致分段错误:
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p)
# error here ^
正确的做法是
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p[])
# fixed ^
了解在何处使用p
和p[]
的最简单方法是思考相应的C代码。在 C 中,我们写
void *p;
create_new_thing(&p)
do_stuff_to_thing(p)
Julia 对象不像 C 对象那样有 first-class 内存地址,所以我们必须在 Julia 中使用 p = Ref{Ptr{Void}}()
来获取内存地址。这个对象作为 ref,在 C 中的行为类似于 &p
。这意味着要获取对象本身,在 C 中为 p
,我们需要在 Julia 中使用 p[]
。
所以 Julia 中的等价物是
p = Ref{Ptr{Void}}() # this p corresponds to &p in C
ccall(:create_new_thing, ..., p) # like &p
ccall(:do_stuff_to_thing, ..., p[]) # like *(&p); that is, like p
好吧,我本来就把这个问题的提法搞砸了(我认真写C++代码已经一年多了,我对纯C的经验非常有限),所以让我们再试一次。
一些 C 代码被编写为期望您执行如下操作
void* p;
create_new_thing(&p); //p is now a new thing
do_stuff_to_thing(p); //something happened to p
我的问题是如何在 Julia 中创建对象 p
。现在我认为答案是
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p)
此外,我相信相同的代码但将 p
声明为 p = Array(Ptr{Void}, 1)
也有效。
然而,我确实发现 Julia 中 Ref
和 Ptr
之间的整个区别非常混乱,主要是因为它们似乎以我无法跟踪的方式相互转换。
您的代码看起来 几乎 不错。不过要小心!任何小错误,例如您在此处遇到的错误,都可能导致分段错误:
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p)
# error here ^
正确的做法是
p = Ref{Ptr{Void}}()
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p)
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p[])
# fixed ^
了解在何处使用p
和p[]
的最简单方法是思考相应的C代码。在 C 中,我们写
void *p;
create_new_thing(&p)
do_stuff_to_thing(p)
Julia 对象不像 C 对象那样有 first-class 内存地址,所以我们必须在 Julia 中使用 p = Ref{Ptr{Void}}()
来获取内存地址。这个对象作为 ref,在 C 中的行为类似于 &p
。这意味着要获取对象本身,在 C 中为 p
,我们需要在 Julia 中使用 p[]
。
所以 Julia 中的等价物是
p = Ref{Ptr{Void}}() # this p corresponds to &p in C
ccall(:create_new_thing, ..., p) # like &p
ccall(:do_stuff_to_thing, ..., p[]) # like *(&p); that is, like p