从Julia调用C函数并将2D数组作为指针作为参数传递

mga*_*gab 8 c julia

的背景

我正在尝试使用ccallJulia函数来使用C语言编写的代码.我知道如何将数组作为参数传递给期望的函数int *arg.例如,尝试使用此C函数

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

这个Julia代码有效

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

问题

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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我需要创建一个数组数组,以便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)
Run Code Online (Sandbox Code Playgroud)

但这种结构结构从朱莉娅方面来说并不是很方便.

问题

  • 有没有其他方法可以将二维矩阵传递给需要该类型参数的C函数int **arg
  • 如果没有,你怎么能够把一个已经存在的朱莉娅的2维数组数组的数组的C结构?
  • 而另一种方式?

meg*_*art 3

我将尝试一一回答您的问题:

是否有其他方法可以将二维矩阵传递给需要 int **arg 类型参数的 C 函数?

是的。您必须向 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)])
Run Code Online (Sandbox Code Playgroud)

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

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

但是,我建议您重写的 cconvert 方法要非常保守,因为其他 Julia 代码可能会期望原始行为。

如果没有,如何将 Julia 中已有的二维数组转换为 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)
Run Code Online (Sandbox Code Playgroud)

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

反过来呢?

我认为这通常是不可能的。为了构造 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)
Run Code Online (Sandbox Code Playgroud)

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