这个问题是Julia - C interface with nonfundamental types的后续问题,有足够的新信息可以被视为不同的问题。我使用的 C 库有两种这样的类型,以及三种可能的版本mystruct:
struct contained {
int x;
int y;
int z;
};
struct mystruct {
int n;
//original:
// contained* arr;
//struct hack version 1:
// contained arr[1];
//struct hack version 2:
contained arr[];
};
Run Code Online (Sandbox Code Playgroud)
使用原始问题的答案,我定义了以下相应的 Julia 类型,它们可以与 的原始版本一起正常工作mystruct,但不能使用 struct hack 的任何一个版本:
type contained
x::Cint
y::Cint
z::Cint
end
type mystruct
n::Cint
arr::Ptr{contained}
end
Run Code Online (Sandbox Code Playgroud)
如果我从 Julia 调用一个 C 函数,它返回 aPtr{mystruct}并将其另存为ms,我可以放置m = unsafe_load(ms)并查看m.n和 指针m.arr,但我只能unsafe_load(m.arr)在原始情况下检查它的值。否则unsafe_load(m.arr)会导致段错误。Julia 中处理包含以这种方式定义的可变长度数组的 C 结构的正确方法是什么?我只会使用mystructwith的原始定义contained *arr,因为它按预期工作,但我也需要适用于其他情况的代码。
正如Julia 手册的 C 接口部分中提到的,关于内联类型/结构成员:
不支持未知大小的数组。
但是,可以使用结构体的地址来计算出数组数据的偏移量(就像在 C 中一样),然后使用unsafe_wrap访问该数据。
这是一个完整的例子:
测试.c
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
int z;
} contained;
typedef struct {
int n;
contained arr[];
} mystruct;
mystruct *return_mystruct() {
mystruct* ms = malloc(sizeof(mystruct) + 6*sizeof(contained));
ms->n = 6;
for (int i=0; i < 6; i++) {
printf("i: %d\n", i);
ms->arr[i].x = i+1;
ms->arr[i].y = i+1;
ms->arr[i].z = i+1;
};
return ms;
}
Run Code Online (Sandbox Code Playgroud)
编译:gcc -shared -o test test.c
朱莉娅:
immutable contained
x::Cint
y::Cint
z::Cint
end
immutable mystruct
n::Cint
end
ms = ccall((:return_mystruct, "test"), Ptr{mystruct}, ())
n = unsafe_load(ms).n
addr = reinterpret(Ptr{contained}, ms+sizeof(mystruct))
arr = unsafe_wrap(Vector{contained}, addr, n)
Run Code Online (Sandbox Code Playgroud)
笔记:
type->immutable以确保布局与C兼容(参见手册)| 归档时间: |
|
| 查看次数: |
313 次 |
| 最近记录: |