Hello,
I have an issue that I can’t figure out regarding returning memory allocated by Julia during embedding.
I tried to simplify the C-code but it’s still a bit verbose :
// Create an array
jl_array_t *jl_make_3d_array(void *existingArray, int *dimsArray)
{
printf("%s \n", __func__);
jl_value_t *array_type = jl_apply_array_type((jl_value_t *)jl_float64_type, 3);
char strDimsBuf[12];
snprintf(strDimsBuf, 12, "(%i, %i, %i)", dimsArray[0], dimsArray[1], dimsArray[2]);
printf("%s \n", strDimsBuf);
jl_value_t *dims = jl_eval_string(strDimsBuf);
jl_array_t *xArray = jl_ptr_to_array(array_type, existingArray, dims, 0);
return xArray;
}
// Call dummy function to test module import
static void external_module_dummy()
{
printf("%s -- BEGIN \n", __FUNCTION__);
{
// Call easy function
jl_module_t *custom_module = (jl_module_t *)jl_eval_string("custom_module");
jl_function_t *dummy = jl_get_function(custom_module, "dummy");
if (dummy != NULL)
{
printf("dummy is not null\n");
}
else
{
printf("dummy is null\n");
return;
}
jl_call0(dummy);
}
printf("\n");
printf("%s -- END \n\n", __FUNCTION__);
return;
}
// Create a 3D Array and square it using custom_module
static void external_module_squareMeBaby_3D()
{
printf("%s -- BEGIN \n", __func__);
jl_module_t *custom_module = (jl_module_t *)jl_eval_string("custom_module");
jl_function_t *func = jl_get_function(custom_module, "squareMeBaby!");
if (func != NULL)
{
printf("squareMeBaby is not Null\n");
}
else
{
printf("squareMeBaby is null\n");
}
printf("%s -> make_array \n", __func__);
double existingArray0[3][4][5];
int length = 3*4*5;
int dimsArray[3];
dimsArray[0] = 3;
dimsArray[1] = 4;
dimsArray[2] = 5;
jl_array_t* xArray = jl_make_3d_array(existingArray0, dimsArray);
double *xData = (double *)jl_array_data(xArray);
for (int i = 0; i < length; i++)
xData[i] = i ;
jl_value_t *ret = jl_call1(func, (jl_value_t *)xArray);
// JL_GC_POP();
printf("%s -> call done \n", __func__);
printf("ret is %p \n\n", ret); // If memory is allocated in squareMeBaby this is a Null pointer
if (!ret)
{
assert(false);
return;
}
{
// Is this necessary ?
JL_GC_PUSH1(&ret);
printf("len(ret)=%li \n", jl_array_len(ret));
printf("rank %i = jl_array_rank(x) \n", jl_array_rank((jl_value_t *)ret));
int d1 = jl_array_dim(ret, 0);
int d2 = jl_array_dim(ret, 1);
double *xResult = jl_array_data(ret);
printf("xResult = [");
for (int i = 0; i < d1; i++)
for (int j = 0; j < d2; j++)
printf("%lf ", xResult[i * d2 + j]);
printf("]\n");
// Is this necessary ?
JL_GC_POP();
}
printf("%s -- END \n", __func__);
return;
}
int main(int argc, char *argv[])
{
jl_init();
jl_eval_string("include(\"test.jl\")");
jl_eval_string("using .custom_module");
external_module_dummy();
external_module_squareMeBaby_3D();
jl_atexit_hook(0);
}
The custom_module is a simple Julia file called test.jl
on the same folder :
module custom_module
using LinearAlgebra
function dummy()
println("Julia says... Hello, world ! Function dummy() from module custom_module has been executed !")
end
function squareMeBaby!(A)
## Square array and return the result
# A[:]=[i*i for i in A] # => This obviously works because it does not allocate memory
B = A * A
return B
end
export dummy
export squareMeBaby!
end
Now in squareMeBaby!
if I modify the data in-place wit hthe syntax A[:] = [i*i for i in A]
it works without issue.
But If I try to return data out of place with the syntax B = A * A
then the pointer returned is Null (abd will results in segfault). I do call JL_GC_PUSH(&ret)
on it but it doesn’t change anything since the pointer itself is NULL.
I’m at loss as what I’m doing wrong here.
EDIT : I also tried this version :
function squareMeBaby(A)
## Square array and return the result
A[:]=[i*i for i in A]
println(typeof(A))
end
and I have a segfault I think println or tyopeof moved something in memory because the Rank and Length I read from the array looks like garbage (rank = 372, length = 140700242326323).
I don’t understand what’s going on…