在 Cxx.jl 提供的数据上使用 Julia 的unsafe_wrap时出现问题



正如标题所示,我在使用Cxx和unsafewrap((时遇到了非常令人困惑的行为。我有一些返回vector<vector<uint8_t>>&的c++代码,我正在Julia中查看。我可以连续两次执行相同的操作,每次都得到不同的答案。我整理了一个代码片段,演示了我所看到的行为:

using Cxx
cxx"""
#include <vector>
struct vholder {
std::vector<std::vector<uint8_t>> data;
vholder() {
std::vector<float> f1{1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1};
std::vector<uint8_t> c1(8*sizeof(float));
std::memcpy(c1.data(), f1.data(), 8*sizeof(float));
data.push_back(c1);
std::vector<float> f2{2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2};
std::vector<uint8_t> c2(8*sizeof(float));
std::memcpy(c2.data(), f2.data(), 8*sizeof(float));
data.push_back(c2);
std::vector<float> f3{3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3};
std::vector<uint8_t> c3(8*sizeof(float));
std::memcpy(c3.data(), f3.data(), 8*sizeof(float));
data.push_back(c3);
std::vector<float> f4{4.4, 4.4, 4.4, 4.4, 4.4, 4.4, 4.4, 4.4};
std::vector<uint8_t> c4(8*sizeof(float));
std::memcpy(c4.data(), f4.data(), 8*sizeof(float));
data.push_back(c4);
}
std::vector<std::vector<uint8_t>>& get_data() {
return data;
}
};
"""
vholder = @cxxnew vholder()
vdata = @cxx vholder->get_data()
jdata = [reinterpret(Complex{Float32}, unsafe_wrap(Array, pointer(v), length(v)))
for v in vdata]
display(jdata)
jdata = [reinterpret(Complex{Float32}, unsafe_wrap(Array, pointer(v), length(v)))
for v in vdata]
display(jdata)

我编写C++部分是为了让Julia完成该部分后的预期结果非常明显。当我运行代码时,我看到的是:

4-element Array{Base.ReinterpretArray{Complex{Float32},1,UInt8,Array{UInt8,1}},1}:
[4.048057f-36 + 0.0f0im, 4.047994f-36 + 0.0f0im, 7.0f-45 + 1.0f-42im, 3.0f-45 + 0.0f0im]  
[1.7337694f-38 + 0.0f0im, 0.0f0 + 0.0f0im, 1.8f-44 + 0.0f0im, 2.0056614f-36 + 0.0f0im]    
[1.7337694f-38 + 0.0f0im, 0.0f0 + 0.0f0im, 1.8f-44 + 0.0f0im, 4.664f-42 + 0.0f0im]        
[6.0541977f-37 + 0.0f0im, 3.1095097f-36 + 0.0f0im, 7.0f-45 + 4.9f-44im, 3.0f-45 + 0.0f0im]
4-element Array{Base.ReinterpretArray{Complex{Float32},1,UInt8,Array{UInt8,1}},1}:
[1.1f0 + 1.1f0im, 1.1f0 + 1.1f0im, 1.1f0 + 1.1f0im, 1.1f0 + 1.1f0im]
[2.2f0 + 2.2f0im, 2.2f0 + 2.2f0im, 2.2f0 + 2.2f0im, 2.2f0 + 2.2f0im]
[3.3f0 + 3.3f0im, 3.3f0 + 3.3f0im, 3.3f0 + 3.3f0im, 3.3f0 + 3.3f0im]
[4.4f0 + 4.4f0im, 4.4f0 + 4.4f0im, 4.4f0 + 4.4f0im, 4.4f0 + 4.4f0im]

我专门设置了c++代码,目的是使返回的对象的生存期比Julia检查它的需要更长,但可能在这方面失败了。

我找到了一个解决方法,可以满足我的特定需求,但不会解释我遇到的奇怪行为。如果我添加std::vector<uint8_t>& get_channel() { return vdata[0]; }作为方法,并调用:

vholder = @cxxnew vholder()
channelVals = @cxx vholder->get_channel()
jvals = reinterpret(Complex{Float32},
unsafe_wrap(Array, pointer(channelVals), length(channelVals)))

然后我得到了预期的结果。因此,在外向量上迭代似乎存在一些问题。我仍然对此感到好奇,所以我不会接受自己的答案(至少目前是这样(。

最新更新