Problem returning vector of custom type in Julia embeeded

embedding

#1

I need to call a Julia function from C++ which returns a Vector of a custom type.
This doesn’t work, the vector has the correct number of elements but they are empty.
I have a Julia type and a Julia function as following :

type Point
  x::Float64
  y::Float64
  z::Float64
end

Base.@ccallable function generate_vector_point()::Vector{Point}
  size = 3
  new_array = Vector{Point}()
  resize!(new_array, size)
  for i = 1:size
    new_array[i] = Point(i + 0.1, i + 0.2, i + 0.3)
    println(i, " : ", new_array[i])
  end
  return new_array
end

According to Julia doc, on the C side, I try to call the previous function as follows :

typedef struct{
	double x;
	double y;
	double z;
} typepoint;						

extern jl_value_t* generate_vector_point();

jl_value_t* retval;
typepoint *p;
retval = generate_vector_point();

if(jl_is_array(retval)) {
	jl_value_t* el1type = (jl_value_t*)jl_array_eltype(retval);
	int sz1 = jl_datatype_size(el1type);
	printf("\n size: el1 %u\n",sz1);
	printf("\n sizeof(typepoint) %u \n", sizeof(typepoint));
	p = (typepoint*)jl_array_data(retval);

	int ndimsret1 = jl_array_ndims(retval);
	size_t sizeret1 = jl_array_dim(retval,0);
	printf(" dims : %u \n",ndimsret1);
	printf(" size(0): %u \n",sizeret1);

	int idx1;
	for (idx1 = 0; idx1 <= sizeret1 - 1; idx1++){
			printf("pntr1 %u %p\n", idx1, &p[idx1]);
			printf("pntr1.x %u %lf\n", idx1, p[idx1].x);
			printf("pntr1.y %u %lf\n", idx1, p[idx1].y);
			printf("pntr1.z %u %lf\n", idx1, p[idx1].z);
	}
}

The output is the following :

1 : Point(1.1, 1.2, 1.3)
2 : Point(2.1, 2.2, 2.3)
3 : Point(3.1, 3.2, 3.3)

size: el1 24
sizeof(typepoint) 24
dims : 1
size(0): 10

pntr1 0 0x7fda971dceb0
pntr1.x 0 0.000000
pntr1.y 0 0.000000
pntr1.z 0 0.000000

pntr1 1 0x7fda971dcec8
pntr1.x 1 0.000000
pntr1.y 1 0.000000
pntr1.z 1 0.000000

pntr1 2 0x7fda971dcee0
pntr1.x 2 0.000000
pntr1.y 2 0.000000
pntr1.z 2 0.000000

NB : I have tried the same pattern with a Vector of Float64 and other base types and it works right.

What am I doing wrong ? Are there a better method to exchange this kind of data between Julia and C ?

Thank you for your help.

Nextor


#2

Does it work if you define your type Point to be immutable? (Just a wild guess)


#3

Indeed, i’ve just tried with :

immutable Point
  x::Float64
  y::Float64
  z::Float64
end

…and it works OK. :frowning:

Any idea about this issue ?


#4

When you are using a mutable type, you are storing pointers to the values in the fields instead of the values themselves in the type. See e.g. https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Struct-Type-correspondences-1


#5

Thank you Kristoffer !

I understand that my Vector{Point} (mutable) is an array of pointers to Point objects. Now, my problem is : how to pass this vector to C / C++ and how to read it in C ?
In Julia doc, there is an example on how to read this kind of data in Julia (example String) but not in the other direction.

In a more large sense, I am trying to produce complex types with arrays / vectors within, typically this kind of structures:

type Cluster
  some_parameter::Int64
  points::Vector{Point}
end

While it is trivial to manage structures, it becomes confused when structures contain Vectors.

Do you know the right way to do that ?

Thank you


#6

Discourse is not letting me answer…

I don’t know if it is a good solution, but you could always write some getx(p) = p.x helper functions in julia and call them on the C side.