首页 > 解决方案 > 如何围绕字符串数组创建一个薄包装器C

问题描述

当使用 Julia 调用 C 时,Julia 可以为 C 分配的现有数据提供一个瘦包装器,这使得 C 和 Julia 之间的数据交换高效。这是 Julia 嵌入部分中著名的在线示例:

double *existingArray = (double*)malloc(sizeof(double)*10);
jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0);

我的问题是:Julia 大师能否提供一个示例,说明如何围绕现有字符串数组创建一个薄包装器(已经在 C 中的堆上分配)

一个后续问题是:我们是否还需要以某种方式处理写障碍?因为字符串数组基本上是一个指针数组,

另一个问题是:当底层数据是字符串数组时,Julia 如何进行 gc 处理:即指针数组,每个指针都指向一个以空字符结尾的字符串的起始地址。

非常感谢!!!

致远

标签: julia

解决方案


看起来 Julia 0.5.2 并没有抱怨以下方法:

假设在 C/C++ 中你有:

char* pchar 指向“A is s\0B is so\0C is som\0D is some\0”,大小:34 = size_all

char** myStrArray 有 4 个指针:指向 "A"、"B"、"C"、D" 的位置,

目标是在不复制的情况下将 pchar 和 myStrArray 传递回 Julia,以便在 Julia 中以某种方式拥有一个字符串数组:

{ "A 是 s", "B 是这样", "C 是 som", "D 是一些" }

在 C/C++ 部分:

jl_value_t* array_type_pointer = jl_apply_array_type(jl_voidpointer_type, 1);
jl_array_t* str_array = jl_ptr_to_array_1d( array_type_pointer, (void*)myStrArray, 4, 1 );
jl_set_nth_field(ret, 14, (jl_value_t*)str_array );

jl_value_t* array_type_uint8 = jl_apply_array_type(jl_uint8_type, 1);
jl_array_t* chr_array = jl_ptr_to_array_1d( array_type_uint8, (uint8_t*)pchar, size_all, 1 );
jl_set_nth_field(ret, 13, (jl_value_t*)chr_array );

请注意,在 jl_ptr_to_array_1d 调用中,最后一个参数 := 1,这意味着 Julia 拥有缓冲区。

在朱莉娅部分

您声明以下两项:

StrVec::Array
StrVecPtr::Array

上面两个都属于ret1,比如说。

julia> String(copy( ret1.StrVec ) )
"A is s\0B is so\0C is som\0D is some\0"

julia> ret1.StrVecPtr
4-element Array{Ptr{Void},1}:
 Ptr{Void} @0x000000000404aa00
 Ptr{Void} @0x000000000404aa07
 Ptr{Void} @0x000000000404aa0f
 Ptr{Void} @0x000000000404aa18

julia> unsafe_string( convert( Ptr{UInt8}, ret1.StrVecPtr[1] ) )
"A is s"

julia> unsafe_string( convert( Ptr{UInt8}, ret1.StrVecPtr[2] ) )
"B is so"

julia> unsafe_string( convert( Ptr{UInt8}, ret1.StrVecPtr[3] ) )
"C is som"

julia> unsafe_string( convert( Ptr{UInt8}, ret1.StrVecPtr[4] ) )
"D is some"

备注:内容包含在 UInt8 的数组中,以 '\0' 分隔,在内存中是连续的,毕竟做 gc 更容易。

如果有人发现一些错误,或者有其他方法,请发布。

非常感谢。


推荐阅读