Is there any official API reference for Julia Embedding in C, or should we be understanding by going through the code or asking here?
And specifically,
How to create and access the data in the tuple?
How to convert a pointer to an array(not 1D) without copying i.e. how to use ‘jl_ptr_to_array’
What should I pass the ‘dims’ argument? Should it be a tuple or svec or 1D array?
In general, the recommended approach is to use the ones described in the doc to evaluate julia code and define your own API. There are other direct runtime interfaces available although those breaks much more often and are not really well documented other than the header itself.
So assume you don’t have any problem creating the type (unless you have a too big type you can just create a big enough buffer to pass in the tuple element types). With that you shouldn’t have any problem allocating the object either so I assume you only have problem with accessing elements.
C does not allow unknown type during compile time so you cannot declare the corresponding C type unless you know it at C code compile time in general. In this particular case though, the three methods I mentioned in the first post still all apply.
You can use the getfield function. It’s accessible in C as jl_get_field. It should be pretty obvious to use. This does not need to rely on any C functions in your code, all offset calculation is down in julia runtime, it’s also the slowest.
You can do offset computation yourself. You can easily predict the layout of the object with n fields. You can just do the offset computation and loads yourself. For NTuple it’s simple enough that you can just cast the pointer to ssize_t* and index it.
It turns out that this is a very special case where it is actually possible to declare a compatible C struct. This require C99 and you can do it as typedef struct { ssize_t a[]; } ntupleint;
It’s April 2024, and this information is still not on the Embedding Julia page It is pretty exciting wasting working hours to learn how to use the Julia C API by looking at the source code.
My advice is to keep the C API exposure to the minimum you need to set up @cfunction pointers and use those to interface between C and Julia. As a bonus this allows you to do things like dynamically loading libjulia.
Thanks, Gunnar, yes, I’ve tried @cfunction last week. Indeed, it is easier to use. However, my use case is that the called functions are determined in runtime, and then I need to write a lot of code to generate @cfunction signature as strings and then use libffi to invoke the resultant C functions.
This is much more complicated in this particular case, then to use jl_call directly. And this approach is much closer to the Python C API, that I have already used. The problem is that the documentation for Julia C API is quite minimalistic, while the code is pretty advanced and lacks docstrings.
For me, libjulia is already linked dynamically in some sense, as the C component in my code that embeds Julia is loaded dynamically via dlopen, so it is also not a problem.
Thank you also for the linke to the repo, I’ll have a look and hopefully understand how to use Julia C API better!
I think you can mostly find how to avoid using the Julia C API there.
I don’t know your constraints but I would, if at all possible, generate the @cfunction signatures with Julia code and in general do as much as possible of the work on the Julia side.