【问题标题】:the proper way to declare C void pointers in Julia在 Julia 中声明 C void 指针的正确方法
【发布时间】:2017-03-01 15:26:13
【问题描述】:

好吧,我最初把这个问题的表述搞砸了(自从我认真编写 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 中 RefPtr 之间的整个区别非常令人困惑,主要是因为它们似乎以我无法跟踪的方式相互转换。

【问题讨论】:

  • 详细信息:void* p;p 是一个“新事物”(对象)。 create_new_thing(&p); 允许函数分配 p 一个值。祝朱莉娅好运。
  • 明白,我没有使用对象这个词的原因是我担心过于具体。例如,可以使用不可变的数字类型来做到这一点。
  • 在 C 中,object通用 术语,表示“数据存储区域...,其内容可以表示值”,如字符、整数、浮点、指针、数组、结构、联合和常量。几乎所有可以指向的东西,除了函数。

标签: c julia void-pointers


【解决方案1】:

您的代码看起来几乎很好。但小心点!任何小错误,例如您在此处遇到的错误,都可能导致分段错误:

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  ^

了解在何处使用pp[] 的最简单方法是考虑相应的C 代码。在C中,我们写

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

Julia 对象不像 C 对象那样具有一流的内存地址,因此我们必须在 Julia 中使用 p = Ref{Ptr{Void}}() 来获取内存地址。这个对象,作为一个引用,行为类似于 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

【讨论】:

  • 第一个ccall签名也应该是Ref{Ptr{Void}},而不是Ptr{Ptr{Void}}docs.julialang.org/en/release-0.5/manual/…
  • @SimonByrne 据我了解,在这种情况下它们是完全等价的,所以我只是保留了 OP 的代码。
  • 我认为它们目前是等价的,但手册推荐Ref 用于可变指针。
  • 感谢您的帮助。我想我现在明白了,我肯定被 Ref 和 Ptr 之间的差异所困扰。我认为就 C 所知,Ref 和 Ptr 是一回事。 Julia 管理 Ref 对象,但仅限于 C 调用的边界。
  • 实际上,我刚刚意识到我实际上是在按照您在回答中提出的建议进行操作,我只是把问题搞砸了。我想我应该彻底检查我的代码,以确保它在任何地方都是正确的。谢谢。
猜你喜欢
  • 2011-10-22
  • 1970-01-01
  • 2021-06-15
  • 2011-03-17
  • 2010-09-18
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
相关资源
最近更新 更多