使用Julia调用C时,Julia可以为C分配的现有数据提供一个瘦包装器,这非常好,这使得C和Julia之间的数据交换有效。这是Julia嵌入部分中著名的在线示例:
humanoid
我的问题是:朱莉娅·古鲁斯(Julia gurus)是否可以提供一个示例,说明如何围绕现有的字符串数组(已在C中的堆中分配)创建一个瘦包装器
一个后续问题是:我们还需要以某种方式照顾写障碍吗?因为字符串数组基本上是指针数组,所以
另一个问题是:当基础数据是字符串数组时,Julia如何进行gc处理:即指针数组,每个指针都指向以空值终止的字符串的起始地址。
非常感谢!
志远
答案 0 :(得分:2)
Julia 0.5.2似乎没有抱怨以下方法:
假设在C / C ++中您有:
char * pchar指向“ A是s \ 0B是so \ 0C是som \ 0D是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。
如果有人发现一些错误或有其他方法,请发表。
非常感谢。