Modifying Julia struct from C

question
interoperability

#1

I want to drive a Julia program from Java. There’s a lot of communication going Java->Julia on a known and very limited number of elements. I’ve come up with a zero-copy approach that I think could work, but need some guidance on whether the approach is sensible. The idea is to allocate some mutable structs in Julia, pass the pointers through to Java, wrap into direct ByteBuffers and modify data+call Julia when necessary.

Currently I’m only trying to get the C->Julia glue to work. On the Julia side the program operates on structs similar to the ones below:

struct Item
    size :: Int64
    value :: Float64
end

mutable struct Shop
    items :: Vector{Item}
    main :: Item
end

global const SHOP = Shop(zeros(Item, 10), Item(0, 0.))

After Julia is initialized, I get the pointer to the SHOP constant from C. From there I can access the array and the lone main Item. I can successfully change the elements of items from C as they seem to be inlined into a contiguous array. However, I have no such luck with the main item using the code below (compiled with g++):

typedef struct {
    int64_t a;
    double b;
} struct_item;

// skipped setup, main function declaration
jl_value_t *shop = jl_eval_string("SHOP");
jl_value_t *array_items_v = jl_get_nth_field_checked(shop, 0);
jl_value_t *main_item_v = jl_get_nth_field_checked(shop, 1);

// Modify the array
jl_array_t *array_items = (jl_array_t*) array_items_v;
struct_item *array_data = (struct_item*) array_items->data;
array_data[0].a = 5;
array_data[0].b = 6.2;
jl_eval_string("println(SHOP)"); // change applied

// Modify the "main" item
((struct_value*) main_item_v)->a = 3;
jl_eval_string("println(SHOP)"); // no change

Could someone please clarify why modifying the value in main_item_v doesn’t work? How can I make it work? Does the array element modification work as expected or is it a lucky coincidence?

Grateful for any and all help!


#2

Your code translate to roughly

array_items_v = shop.items
main_item_v = shop.main

array_items_v[1].a = 5
array_items_v[1].b = 6.2

main_item_v.a = 3

which has two problems (really the same problem).

  1. the main_item_v.a = 3 is undefined. You can crash julia this way.
  2. Item is stored inline. The pointer you get is unrelated to where the field is stored.

(Both of the above are due to Item being immutable)

The best way to do all of these is simply declaring the structure in C rather than going through julia API.

typedef struct {
    jl_array_t *items;
    struct_item item;
} struct_shop;

//
... *shop = (struct_shop*)...;
... array_items = shop->items;
...

shop->item.a = 3;
...

#3

Thanks, worked like a charm!