在Julia中声明C void指针的正确方法

时间:2022-08-25 18:51:44

Ok, I originally badly screwed up my formulation of this question (it's more than a year now since I seriously wrote C++ code and I have pretty limited experience with pure C), so let's try again.

好吧,我最初严重搞砸了我对这个问题的描述(自从我认真编写C ++代码以来我已经超过一年了,我对纯C的经验非常有限),让我们再试一次。

Some C code is written to expect you to do something like the following

编写一些C代码以期望您执行以下操作

void* p;
create_new_thing(&p);  //p is now a new thing
do_stuff_to_thing(p);  //something happened to p

My question is how to create the object p in Julia. Right now I believe the answer to be

我的问题是如何在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)

Furthermore, I believe the same code but with p declared instead as p = Array(Ptr{Void}, 1) also works.

此外,我相信相同的代码,但p声明为p = Array(Ptr {Void},1)也有效。

I do however find the whole distinction between Ref and Ptr in Julia very confusing, mostly because they seem to get converted between each other in ways I cannot keep track of.

然而,我确实发现朱莉娅的Ref和Ptr之间的整体区别非常令人困惑,主要是因为它们似乎在我无法跟踪的方式之间相互转换。

1 个解决方案

#1


9  

Your code looks almost fine. But be careful! Any small error, like the one you have here, can cause a segmentation fault:

你的代码看起来很好。不过要小心!任何小错误,如您在这里的错误,都可能导致分段错误:

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  ^

The correct way to do it is

正确的方法是

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  ^

The easiest way to understand where to use p and p[] is to think of the corresponding C code. In C, we write

理解p和p []的使用位置的最简单方法是考虑相应的C代码。在C中,我们写

void *p;
create_new_thing(&p)
do_stuff_to_thing(p)

Julia objects do not have first-class memory addresses like C objects do, so we must use p = Ref{Ptr{Void}}() in Julia to get a memory address. This object, as a ref, behaves like &p in C. That means to get the object itself, p in C, we need to use p[] in Julia.

Julia对象没有像C对象那样的第一类内存地址,所以我们必须在Julia中使用p = Ref {Ptr {Void}}()来获取内存地址。这个对象,作为ref,表现得像C中的&p。这意味着要获得对象本身,p在C中,我们需要在Julia中使用p []。

So the equivalent in Julia is

所以朱莉娅的等价物是

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

#1


9  

Your code looks almost fine. But be careful! Any small error, like the one you have here, can cause a segmentation fault:

你的代码看起来很好。不过要小心!任何小错误,如您在这里的错误,都可能导致分段错误:

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  ^

The correct way to do it is

正确的方法是

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  ^

The easiest way to understand where to use p and p[] is to think of the corresponding C code. In C, we write

理解p和p []的使用位置的最简单方法是考虑相应的C代码。在C中,我们写

void *p;
create_new_thing(&p)
do_stuff_to_thing(p)

Julia objects do not have first-class memory addresses like C objects do, so we must use p = Ref{Ptr{Void}}() in Julia to get a memory address. This object, as a ref, behaves like &p in C. That means to get the object itself, p in C, we need to use p[] in Julia.

Julia对象没有像C对象那样的第一类内存地址,所以我们必须在Julia中使用p = Ref {Ptr {Void}}()来获取内存地址。这个对象,作为ref,表现得像C中的&p。这意味着要获得对象本身,p在C中,我们需要在Julia中使用p []。

So the equivalent in Julia is

所以朱莉娅的等价物是

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