# Pass (to Julia) a C struct which contains a pointer to another struct

**URL:** <https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406>\
**Category:** General Usage\
**Tags:** array, struct\
**Created:** [August 6, 2020, 9:13am UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406 "2020-08-06T09:13:18Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 6, 2020, 9:13am UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/1 "2020-08-06T09:13:18Z")

</div>

Dear experts,  
assume the module below:

```julia
module PointsModule

struct Point
	x::Cdouble
	y::Cdouble
	z::Cdouble
end

struct Points
	n_of_points::Cint
	all_points::Vector{Point}
end

function sum_points(my_points::Points)::Cdouble
	println("Received ", my_points.n_of_points)
	println("x[1] = ", my_points.all_points[1].x, " x[2] = ", my_points.all_points[2].x)
	return my_points.all_points[1].x + my_points.all_points[2].x
end

function show_point(my_point::Point)
	println("x = ", my_point.x)
	println("y = ", my_point.y)
	println("z = ", my_point.z)
end

if abspath(PROGRAM_FILE) == @ __FILE__
	a_p = Point(1.0,2.0,3.0)
	b_p = Point(4.0,5.0,6.0)
	c_p = Point(7.0,8.0,9.0)

	show_point(a_p)

	my_points = Points(3,[a_p, b_p, c_p])

	res = sum_points(my_points)
	println("Res is: ", res)

end

end

```

I would like to call the `sum_points` from my C++ code.  
Here is my C++ code:

```julia
#include <iostream>
#include <string>

#include <unistd.h>

#include <julia.h>

JULIA_DEFINE_FAST_TLS()

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

typedef struct 
{
	size_t nr_of_points;
	Point* all_points;
}Points;

void fill_struct(Points* my_points)
{
	const size_t nr_of_points(600*600);
	my_points->nr_of_points = nr_of_points;
	my_points->all_points = new Point[nr_of_points];

	for(size_t i=0; i<nr_of_points; i++)
	{
		my_points->all_points[i].x = 1.5;
		my_points->all_points[i].y = 2.7;
		my_points->all_points[i].z = 3.9;
	}
}

int main()
{
	jl_options.image_file = JULIAC_PROGRAM_LIBNAME;
    julia_init(JL_IMAGE_JULIA_HOME);

	Points my_points;

	fill_struct(&my_points);

	jl_value_t* mod = (jl_value_t*) jl_eval_string("PointsModule");

	jl_value_t**jl_point_ptr = (jl_value_t**) malloc (my_points.nr_of_points * sizeof( (jl_value_t*) jl_get_function((jl_module_t*)mod, "Point") ));

	for(size_t i=0; i<my_points.nr_of_points; i++)
	{
		jl_value_t* jl_x = NULL;
		jl_value_t* jl_y = NULL;
		jl_value_t* jl_z = NULL;
		JL_GC_PUSH3(jl_x, jl_y, jl_z);
		jl_x = jl_box_float64(my_points.all_points[i].x);
		jl_y = jl_box_float64(my_points.all_points[i].y);
		jl_z = jl_box_float64(my_points.all_points[i].z);

		jl_point_ptr[i] = jl_new_struct((jl_datatype_t*)jl_get_function((jl_module_t*)mod, "Point"),
		                                          jl_x,
		                                          jl_y,
		                                          jl_z);
	}

	jl_function_t* jl_show_point = jl_get_function((jl_module_t*)mod, "show_point");
	jl_call1(jl_show_point, jl_point_ptr[0]);
	jl_call1(jl_show_point, jl_point_ptr[1]);

	jl_value_t* jl_nr_of_points = NULL;
	jl_array_t* jl_point_array = NULL;
	JL_GC_PUSH2(jl_nr_of_points, jl_point_array);
	jl_nr_of_points = jl_box_int64(my_points.nr_of_points);
	jl_point_array = jl_ptr_to_array_1d(jl_apply_array_type((jl_value_t*)jl_get_function((jl_module_t*)mod, "Point"), 1),
		                                                               jl_point_ptr,
		                                                               my_points.nr_of_points,
		                                                               0);

	jl_value_t* jl_my_points = jl_new_struct((jl_datatype_t*)jl_get_function((jl_module_t*)mod, "Points"),
											 jl_nr_of_points,
											 jl_point_array);

	jl_function_t* jl_sum_points = jl_get_function((jl_module_t*)mod, "sum_points");
	jl_value_t* res = jl_call1(jl_sum_points, jl_my_points);

	std::cout << "Res is: "	<< jl_unbox_float64(res) << std::endl;
	JL_GC_POP();

	jl_atexit_hook(0);

return 0;
}

```

On the above example, I created the `jl_point_ptr` which is an array of` jl_new_struct` objects ( = `jl_value_t*` ).  
Then, inside the for loop I am assigning each element of the `jl_point_pt`r to an allocation `jl_new_struct` object.  
Once all the points are created, I am creating a “pointer to an array” as I would do if I had an array of primitive types.  
Although the `jl_point_array` is created fine, when I pass it in the `jl_sum_points` function, all the elements are empty.

Could you help me please?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 6, 2020, 1:27pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/2 "2020-08-06T13:27:36Z")

</div>

And this is exactly why I recommend against it in [Passing a C struct into Julia](https://discourse.julialang.org/t/passing-a-c-struct-into-julia/43965) .

Unless you are completely familar with all the layout, you should use the C types to pass data around, rather than trying to create julia arrays etc. Even if you do, it’s still less efficient to create those julia types in C. (and you can create the necessary C layout compatible julia types using “native” C or generic julia C api and it’s much better to use the native one.)

And again, if you have a pointer in your C struct, use a pointer in your julia struct as well.

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 6, 2020, 2:42pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/3 "2020-08-06T14:42:09Z")

</div>

Hi yuyichao,  
thanks for swift answer!  
Then, if I would change to:

```julia
struct Point
	x::Cdouble
	y::Cdouble
	z::Cdouble
end

struct Points
	n_of_points::Cint
	all_points::Ptr{Point}
end

```

I am not managing to create successfully the Ptr within Julia:

```julia
module PointsModule

struct Point
	x::Cdouble
	y::Cdouble
	z::Cdouble
end

struct Points
	n_of_points::Cint
	all_points::Ptr{Point}
end

function sum_points(my_points::Points)::Cdouble
	println("Received ", my_points.n_of_points, "; Check memory")
	println("x[1] = ", unsafe_load(my_points.all_points,1), " x[2] = ", unsafe_load(my_points.all_points,2).x)
	return 0.1
end

function show_point(my_point::Point)
	println("x = ", my_point.x)
	println("y = ", my_point.y)
	println("z = ", my_point.z)
end

if abspath(PROGRAM_FILE) == @ __FILE__
	a_p = Point(1.0,2.0,3.0)
	b_p = Point(4.0,5.0,6.0)
	c_p = Point(7.0,8.0,9.0)

	my_point_array = [a_p, b_p, c_p]
       my_ptr = Ptr{Point}(pointer_from_objref(my_point_array))

	show_point(a_p)

	my_points = Points(3,my_ptr)

	res = sum_points(my_points)
	println("Res is: ", res)

end

end

```

As you see, in the function `sum_points` I am simply printing the data.  
the printed data is:  
`x[1] = Main.PointsModule.Point(6.8985861740936e-310, 1.5e-323, 2.812953e-318) x[2] = 1.5e-323`  
which means that the pointer is not pointing to the proper version.  
What am I doing wrong?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 6, 2020, 2:52pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/4 "2020-08-06T14:52:32Z")

</div>

> [@Vangelis](#):
>
> `pointer_from_objref`

`pointer`

If you are creating the C pointer in jula, you also need to make sure the object remains valid, with `GC.@preserve my_point_array` over the duration the pointer is used (rest of the `if`). If it’s just a test it’s ok for now since it’s in global scope.

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 6, 2020, 2:54pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/5 "2020-08-06T14:54:46Z")

</div>

thanks!!!  
It worked!

a bit later I will try the call from C 🙂

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 7, 2020, 9:15am UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/6 "2020-08-07T09:15:58Z")

</div>

Hi Yuyichao,  
now the problem is when I call it from C.  
Here is the code:

```julia
#include <iostream>
#include <string>
#include <vector>

#include <unistd.h>

#include <julia.h>

JULIA_DEFINE_FAST_TLS()

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

typedef struct 
{
	size_t nr_of_points;
	Point* all_points;
}Points;

void fill_struct(Points* my_points)
{
	const size_t nr_of_points(600*600);
	my_points->nr_of_points = nr_of_points;
	my_points->all_points = new Point[nr_of_points];

	for(size_t i=0; i<nr_of_points; i++)
	{
		my_points->all_points[i].x = 1.5;
		my_points->all_points[i].y = 2.7;
		my_points->all_points[i].z = 3.9;
	}
}

int main()
{
	jl_options.image_file = JULIAC_PROGRAM_LIBNAME;
    julia_init(JL_IMAGE_JULIA_HOME);

	Points my_points;

	fill_struct(&my_points);

	jl_value_t* mod = (jl_value_t*) jl_eval_string("PointsModule");

	jl_value_t**jl_point_ptr = (jl_value_t**) malloc (my_points.nr_of_points * sizeof( (jl_value_t*) jl_get_function((jl_module_t*)mod, "Point") ));

	for(size_t i=0; i<my_points.nr_of_points; i++)
	{
		// std::cout << "Entering for i=" << i << std::endl;
		jl_value_t* jl_x = NULL;
		jl_value_t* jl_y = NULL;
		jl_value_t* jl_z = NULL;
		JL_GC_PUSH3(jl_x, jl_y, jl_z);
		jl_x = jl_box_float64(my_points.all_points[i].x);
		jl_y = jl_box_float64(my_points.all_points[i].y);
		jl_z = jl_box_float64(my_points.all_points[i].z);

		jl_point_ptr[i] = jl_new_struct((jl_datatype_t*)jl_get_function((jl_module_t*)mod, "Point"),
		                                          jl_x,
		                                          jl_y,
		                                          jl_z);
	}

	jl_function_t* jl_show_point = jl_get_function((jl_module_t*)mod, "show_point");
	jl_call1(jl_show_point, jl_point_ptr[0]);
	jl_call1(jl_show_point, jl_point_ptr[1]);

	jl_value_t* jl_nr_of_points = NULL;
	jl_array_t* jl_point_array = NULL;
	JL_GC_PUSH1(jl_nr_of_points);
	jl_nr_of_points = jl_box_int64(my_points.nr_of_points);
	jl_point_array = jl_ptr_to_array_1d(jl_apply_array_type((jl_value_t*)jl_get_function((jl_module_t*)mod, "Point"), 1),
	 	                                                               jl_point_ptr,
	 	                                                               my_points.nr_of_points,
	 	                                                               0);

	jl_value_t* jl_my_points = jl_new_struct((jl_datatype_t*)jl_get_function((jl_module_t*)mod, "Points"),
											 jl_nr_of_points,
											 jl_point_array);

	jl_function_t* jl_sum_points = jl_get_function((jl_module_t*)mod, "sum_points");
	jl_value_t* res = jl_call1(jl_sum_points, jl_my_points);

	std::cout << "Res is: "	<< jl_unbox_float64(res) << std::endl;

	JL_GC_POP();

	jl_atexit_hook(0);

return 0;
}

```

The `jl_my_points` is created without problem, but when it calls the `jl_sum_points` I am getting the following error:

```julia
signal (11): Segmentation fault
in expression starting at none:0
unsafe_load at ./pointer.jl:105 [inlined]
sum_points at /home/eparadas/tests/Julia/memory_tests/PointsModule.jl:16
jfptr_sum_points_65770 at /home/eparadas/tests/Julia/memory_tests/libpoints_sys.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2214 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2398
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1690 [inlined]
jl_call1 at /buildworker/worker/package_linux64/build/src/jlapi.c:226
main at ./call_points_feval (unknown line)
__libc_start_main at /lib64/libc.so.6 (unknown line)
_start at ./call_points_feval (unknown line)
Allocations: 2543 (Pool: 2532; Big: 11); GC: 0
Segmentation fault

```

As it points out, it is related to the `unsafe_load`.

How could it be solved?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 7, 2020, 1:32pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/7 "2020-08-07T13:32:21Z")

</div>

You just need to store the pointer to the struct, you are again trying to store an julia array instead. Also, the array layout is wrong but that’s not the problem here…

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 7, 2020, 1:39pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/8 "2020-08-07T13:39:31Z")

</div>

If I understood correctly, you mean this:

```julia
jl_value_t* jl_my_points = jl_new_struct((jl_datatype_t*)jl_get_function((jl_module_t*)mod, "Points"),
											 jl_nr_of_points,
											 jl_point_ptr);

```

where the `jl_point_ptr` is defined as:

```julia
jl_value_t**jl_point_ptr = (jl_value_t**) malloc (my_points.nr_of_points * sizeof( (jl_value_t*) jl_get_function((jl_module_t*)mod, "Point") ));

```

Doing that, it fails to construct the struct, with the error:

```julia
signal (11): Segmentation fault
in expression starting at none:0
jl_assign_bits at /buildworker/worker/package_linux64/build/src/datatype.c:697 [inlined]
set_nth_field at /buildworker/worker/package_linux64/build/src/datatype.c:1075 [inlined]
jl_new_struct at /buildworker/worker/package_linux64/build/src/datatype.c:883
main at ./call_points_feval (unknown line)
__libc_start_main at /lib64/libc.so.6 (unknown line)
_start at ./call_points_feval (unknown line)
Allocations: 2544 (Pool: 2533; Big: 11); GC: 0
Segmentation fault

```

The `jl_new_struct` returns a `jl_value_t*`  
Therefore, the `jl_point_ptr` should be `jl_value_t**`, right?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 7, 2020, 2:02pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/9 "2020-08-07T14:02:12Z")

</div>

> [@Vangelis](#):
>
> where the `jl_point_ptr` is defined as:

No.

1. You already have your pointer, you don’t need to allocate a new one.
2. You are using C `sizeof` on a pointer, that’s not going to give you the correct result.
3. The type is not `jl_value_t**` and simply `Point*`.
4. If you really want to use `jl_new_struct`, which I still don’t recommend, you should box the pointer to a julia object.

And again, you already have the C object and declared a compatible julia one, you just need to copy the content of the C object to a julia object and you’ll be done.

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 7, 2020, 2:09pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/10 "2020-08-07T14:09:54Z")

</div>

> [@yuyichao](#):
>
> You are using C `sizeof` on a pointer, that’s not going to give you the correct result.

indeed

> [@yuyichao](#):
>
> If you really want to use `jl_new_struct` , which I still don’t recommend, you should box the pointer to a julia object.

if so, what would be the julia object then?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 7, 2020, 3:41pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/11 "2020-08-07T15:41:28Z")

</div>

It’s a julia `Ptr{Point}`, exactly as you declared in julia code.

---

<div class="post-metadata">

**Author:** ![Vangelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vangelis/32/14063_2.png) [@Vangelis](https://discourse.julialang.org/u/Vangelis)\
**Post date:** [August 7, 2020, 3:51pm UTC](https://discourse.julialang.org/t/pass-to-julia-a-c-struct-which-contains-a-pointer-to-another-struct/44406/12 "2020-08-07T15:51:49Z")

</div>

Thanks for all the help Yuyichao!  
Much appreciated!
