从Julia调用C函数并传递2D数组作为指针的指针作为参数 [英] Calling a C function from Julia and passing a 2D array as a pointer of pointers as argument

查看:238
本文介绍了从Julia调用C函数并传递2D数组作为指针的指针作为参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to use the ccall Julia function to use code written in C. I know how to pass an array as an argument to a function that expects int *arg. For example, trying to use this C function

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函数来说,它似乎并非如此简单,因为C函数希望将指向指针(int **arg)的指针用作二维矩阵.说这个

The problem

It doesn't seem to be so straight forward with C functions that expect a pointer to a pointer (int **arg) to be used as a 2-dimensional matrix. Say this one

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代码可以接受它:

Here, I needed to create an Array of Arrays so that the C code would accept it:

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的角度来看,这种结构结构不是很方便.

But this structure structure is not very convenient from the Julia side.

  • 还有其他方法可以将二维矩阵传递给C函数,该函数期望参数为int **arg类型吗?
  • 如果没有,如何将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?
  • If not, how can you transform an already existing 2-dimensional array of Julia to the array of arrays structure of C?
  • and the other way around?

推荐答案

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

I will try to answer you questions one by one:

还有其他方法可以将二维矩阵传递给C函数,该函数需要一个int ** arg类型的参数吗?

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}}的转换.因此,您定义:

Yes. You have to add a method to julia's cconvert function so that it does the conversion from Matrix{Cint} to Ptr{Ptr{Cint}}. So you define:

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

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

(see next question for explanation) and can afterwards directly pass your matrix to ccall:

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

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

However, I would suggest to be very conservative in which cconvert methods you overwrite, because other julia code might expect the original behavior.

如果没有,如何将已经存在的二维Julia数组转换为C的数组结构?

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中:

The following should work: You generate an Array of pointers to every column of your matrix, so in 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)

Now the matrix xx2 is filled by the C function. Note that in julia v0.3 you have to replace Ref(xx2,i) with pointer(xx2,i)

反过来呢?

and the other way around?

我认为这通常是不可能的.为了构造julia 2D数组,数据必须位于连续的内存块中.如果您确实有信心,可以这样做:

I don't think this is generally possible. In order to construct a julia 2D array, the data must be in a contiguous block of memory. If you are REALLY confident this is the case you can do:

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释放.

Which returns the original matrix. Here, the last argument to pointer_to_array determines, if Julia takes the ownership of the array and the data should be freed by Julia's gc.

这篇关于从Julia调用C函数并传递2D数组作为指针的指针作为参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆