在Julia中将指向struct的指针作为参数传递

时间:2015-05-31 19:06:30

标签: julia

我有一个与C结构相对应的类型定义,如下所示:

{{1}}

如何在ccall中为c函数传递一个指向此类型的指针作为输入参数(即struct CStruct *)?

旧文档(v0.3)建议在ccall的输入参数列表中使用& var。但是,在v0.4文档中删除了该语句(同样,& var在v0.4中不起作用)。

3 个答案:

答案 0 :(得分:0)

使用Ref{fakeCStruct}

r = Ref(fakeCStruct(3, 4))
ccall((:somefunction, "lib"), Void, (Ref{fakeCStruct},), r)

来自System Independenthere中的Julia文档:

C name:                                                   |   Julia base type
T* (where T represents an appropriately defined type)     |     Ref{T}

答案 1 :(得分:0)

为Julia对象分配内存,然后通过指针传递它:

type fakeCStruct
  a::UInt8;
  b::UInt32;
end

var = fakeCStruct(3,4)

var_p = Ptr{fakeCStruct}(pointer_from_objref(var))

ccall((:somefunc, "lib"), Void, (Ptr{fakeCStruct},), var_p)

(使用Ref {}并不适合我...使用Julia 0.4.0)

答案 2 :(得分:0)

尽管我绝对不是专家,但我还是迭代了一些对我有用的代码。希望这会帮助人们。在示例中,foo.c被编译为共享库(在我的情况下为.dll),并从foo.jl进行调用。

foo.c

struct mystruct {
    int a;
    int b;
};

typedef struct mystruct mystruct_t;

int recvstruct(mystruct_t* st) {
    printf("C %u, %u\n", st->a, st->b);
    return 0;
}

mystruct_t* updatestruct(mystruct_t* st) {
    // here we need to return the pointer, since Julia seems to 
    // pass a pointer to a copy of the struct
    st->a = 10;
    st->b = 11;
    return st;
}

foo.jl

struct mystruct
    a::Int32
    b::Int32
end

function let_c_print_struct()
    # Note that the function call automatically converts `mystruct(3, 4)` to `::Ref(..)`.
    ccall((:recvstruct, libfile), Int32, (Ref{mystruct},), mystruct(3, 4))
end

function let_c_update_struct()
    st = mystruct(5, 6)
    ret = ccall((:updatestruct, libfile), Ref{ mystruct }, (Ref{ mystruct }, ), st)

    @show st # st = mystruct(5, 6)
    @show ret[] # ret[] = mystruct(10, 11) 
end

关于共享库中数据的生命周期:我发现存储在内存中的对象仍然可用(我想它们超出了垃圾收集器的范围)。四个观察结果证明数据仍然可用:

  • Julia保持库处于打开状态,除非明确将其关闭。
  • Julia语言源代码对从unsafe_string返回的值使用ccall(取消引用指针)。查看unsafe_string(ccall(的搜索结果。
  • 我发现在C中分配数据(甚至包含指针的结构)并在Julia中传递对该数据的引用确实可行。
  • 我发现套接字保持打开状态。