Hi,
I’m trying to wrap RCpp C++ code for use from Julia. The original code used R objects created from C++ to pass back arrays created in C++. I don’t understand what I have to do to correctly change the code for Julia without creating segfaults and the like.
I have modified the extern C function to return a pointer to a struct. This struct stores three array pointers and an Int, which is the length of all three arrays.
I can call the compiled library like this, and I do get correct looking values within C++, so I think I’m doing something correct at least. But calling the function multiple times segfaults, as does printing the return tuple, and other things I randomly tried:
result = ccall((:isobands_impl, "isobands.so"),
Ptr{Tuple{Ptr{Float64},Ptr{Float64},Ptr{Int},Int}},
(Ptr{Float64}, Int, Ptr{Float64}, Int, Ptr{Float64}, Int, Int, Float64, Float64),
collect(1:4.0), 4,
collect(1:5.0), 5,
vec(rand(4, 5)), 5, 4,
0.0, 1.0);
Then I can do this
julia> tup = unsafe_load(result)
(Ptr{Float64} @0x00007f974d3b3710, Ptr{Float64} @0x00007f974a8daa80, Ptr{Int64} @0x00007f974a890cc0, 14)
But this doesn’t work as the values are garbage. I’ve printed the values from within the C++ function and they should be different.
julia> unsafe_wrap(Vector{Float64}, tup[1], tup[4], own = false)
14-element Array{Float64,1}:
6.9311400044737e-310
6.9311400044737e-310
6.9311382644069e-310
6.9311382644085e-310
6.93113660802377e-310
6.93113664137636e-310
0.0
6.9311366080206e-310
1.489573e-317
4.0e-323
6.93113660596687e-310
0.0
0.0
5.0927898983e-313
Here I’ll paste the last part of the C++ function which returns the data, maybe someone can spot a glaring error there. I’m by no means an expert in any of this, so please be gentle
// the struct I defined for my return type
struct resultStruct {
double *x;
double *y;
int *id;
int len;
};
// end of the function I'm calling
tuple<vector<double>, vector<double>, vector<int> > result = ib.collect();
vector<double> res_x = get<0>(result);
vector<double> res_y = get<1>(result);
vector<int> res_id = get<2>(result);
// I checked that these contain the correct data
// cout << "xs: " << res_x.size() << endl;
// for (auto i: res_x) {
// cout << i << endl;
// }
// cout << "ys: " << res_y.size() << endl;
// for (auto i: res_y) {
// cout << i << endl;
// }
// cout << "id :" << res_id.size() << endl;
// for (auto i: res_id) {
// cout << i << endl;
// }
int len = res_x.size();
struct resultStruct* returnvalue;
returnvalue->x = res_x.data();
returnvalue->y = res_y.data();
returnvalue->id = res_id.data();
returnvalue->len = len;
return returnvalue;