从 Julia 调用 C 函数并将二维数组作为指针的指针作为参数传递

标签 c julia

背景

我正在尝试使用 ccall Julia 函数来使用用 C 编写的代码。 我知道如何将数组作为参数传递给需要 int *arg 的函数。例如,尝试使用这个 C 函数

void sum_one(int *arr, int len)
{
  for (int i=0; i<len; i++){
    arr[i]++;
  }
}

这个 Julia 代码有效

x = collect(Cint, 1:5)
ccall((:sum_one, "/path/to/mylib.so"), Void, (Ptr{Cint}, Cint), x, 5)

问题

C 函数似乎并没有那么直接,它期望将指向指针 (int **arg) 的指针用作二维矩阵。说这个

void fill_matrix(int **arr, int row, int col)
{
  for (int i=0; i<row; i++){
    for (int j=0; j<col; j++){
      arr[i][j] = arr[i][j] + i + j*10;
    }
  }
}

在这里,我需要创建一个数组的数组,以便 C 代码可以接受它:

xx = [zeros(Cint, 5) for i in 1:6]
ccall((:fill_matrix, "/path/to/mylib.so"),
       Void, (Ptr{Ptr{Cint}}, Cint, Cint), xx, 6,5)

但是这个结构体结构从Julia端来看不是很方便。

问题

  • 是否有任何其他方法可以将二维矩阵传递给需要类型为 int **arg 的参数的 C 函数?
  • 如果不是,您如何将 Julia 的二维数组转换为 C 的数组数组结构?
  • 反过来呢?

最佳答案

我会尽量一一回答你的问题:

Is there any other way to pass a 2-dimensional matrix to a C function that expects an argument of the type int **arg?

是的。您必须向 julia 的 cconvert 函数添加一个方法,以便它执行从 Matrix{Cint}Ptr{Ptr{Cint}} 的转换.所以你定义:

Base.cconvert(::Type{Ptr{Ptr{Cint}}},xx2::Matrix{Cint})=Ref{Ptr{Cint}}([Ref(xx2,i) for i=1:size(xx2,1):length(xx2)])

(参见下一个问题的解释)然后可以直接将矩阵传递给 ccall:

xx2=zeros(Cint,5,6)
ccall((:fill_matrix, "mylib.so"),Void, (Ptr{Ptr{Cint}}, Cint, Cint), xx2, 6,5)

但是,我建议您在覆盖哪些 cconvert 方法时非常保守,因为其他 julia 代码可能期望原始行为。

If not, how can you transform an already existing 2-dimensional array of Julia to the array of arrays structure of C?

以下应该有效:您生成一个指向矩阵每一列的指针数组,因此在 julia-0.4 中:

xx2=zeros(Cint,5,6)
refAr=[Ref(xx2,i) for i=1:size(xx2,1):length(xx2)]
ccall((:fill_matrix, "mylib.so"),Void, (Ptr{Ptr{Cint}}, Cint, Cint), refAr, 6,5)

现在矩阵 xx2 由 C 函数填充。请注意,在 julia v0.3 中,您必须将 Ref(xx2,i) 替换为 pointer(xx2,i)

and the other way around?

我认为这通常是不可能的。为了构建 julia 二维数组,数据必须位于连续的内存块中。如果您真的有信心,您可以这样做:

p=pointer(refAr)  # This is a Ptr{Ptr{Cint}} representing the int**
aa=pointer_to_array(p,6,false)
bb=pointer_to_array(aa[1],(5,6),false)

返回原始矩阵。在这里,pointer_to_array 的最后一个参数决定了 Julia 是否取得数组的所有权并且数据应该由 Julia 的 gc 释放。

关于从 Julia 调用 C 函数并将二维数组作为指针的指针作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33003174/

相关文章:

c - 如何使用公式来显示给定结果而不是使用 if、else?

c - 查找段错误而不导致崩溃

c - 如何水平移动星形图案?

Julia GLM - 使用 devresid 进行绘图

julia - 如何根据变量值在函数内定义函数

c - 使用 Swig 将字符串列表从 C 函数发送到 TCL 进程

c - 为什么在函数中使用字符串参数时退出程序后我的变量损坏(运行时检查失败)

julia - 如何轻松更新 Julia 0.4?

memory-management - 广播分配大量内存whist for循环不会

julia - 如何向 Julia 中的特定 URL 发出请求?