How to define a Julia function from C?

Hi all,

I’m a bit new to the Julia community, coming more from the Python / NumPy space. I’ve been using Julia internally for a while, and have spun part of my work out into a open-source package I hope to announce soon.

I’m doing some cross-language stuff (notably Julia and JavaScript), so a fair amount of this work is in C. I’d like to be able to define a new Julia function in C itself. Is this possible? I haven’t found good examples of it online.

Cheers,

Irwin

1 Like

See the embedding example or search for jl_eval_string on StackOverflow.

If you mean define a C function that accepts/returns Julia values (jl_value_t*), then a large fraction of the code in src/ can serve as an example… Just start grepping for ccall(:jl_ in base/. (e.g.: jl_parse_string, jl_new_array, etc.)

You may also be interested in node-julia. I think it’s unmaintained at the moment, but forking and updating it should be a lot less work than building everything from scratch.

Thanks! A search for ccall(:jl showed me exactly what I wanted, which was kind of obvious in hindsight – just a function with some jl_value_t args.

While ccall from Julia is great, is it possible to get the method defined as a global through the C API itself? In my case, I already have a C init function that needs to be called, so I may as well get my global defs set there. Basically, given an appropriate C function, is it possible to combine jl_set_global along with something like jl_method_def / jl_generic_function_def / … (I have no idea what those do) to create a Julia function? Basically I’m after ccall in the C API.

As for node-julia, I’m very aware. It appears great, but also appears unmaintained as you mentioned – it didn’t work for me and I tried to fix it, but couldn’t. I just built new JS bindings from scratch, which may or may not be useful – I’ll announce when I feel they are ready.

Irwin

I’m confused – isn’t the C API for ccall just calling a function in C?

I think he wants to define the wrapper in C.

In principle you could do something like PyMethodDef, but it seems like a lot of unnecessary pain when you are carrying around a giant JIT anyway. If you really need that, the place to start is probably reading the section for method_sym in interpreter.c.

If you just need a C-callable pointer to a Julia function, then use jl_function_ptr (see the definition of cfunction in base.jl).

yuyichao and ihnorton got it exactly – maybe it’s because I’m used to Python but, yeah, I was looking for the equivalent of PyMethodDef. interpreter.c is a good place to look, thanks for that – but I’ll see if I can do something with ccall.

Thanks!

Irwin

[edit: as barche pointed out, there are a handful of C-defined jl_f_ functions in builtins.c, for bootstrapping]

PyMethodDef exists in Python because it’s the only viable option, and similarly in other interpreted languages. (well, extension interop could be done with ctypes/libffi, but the marshaling overhead would probably be huge).

What I’m suggesting is basically:

jl_init(...)
...
jl_value_t* myfunc = jl_eval_string("myfunc(args) = ccall((:myfunc, :mylib), Any, (...), args)")

You can store that handle, call it with jl_call[0/1...] etc.

It seems the C API for defining functions is not as complete as the one for defining types using jl_new_datatype. I once tried applying what’s done in add_builtin_func, but the result was a lot less flexible than what can be done by defining a function with different methods in Julia.

CxxWrap.jl allows defining functions from C++, but it cheats by feeding the data (function pointer, return and argument types) back to Julia and then using metaprogramming to create a new Julia function that makes the ccall. In case this fits your workflow, see here for a simple example:
C++:
https://github.com/JuliaInterop/CxxWrap.jl/blob/master/deps/src/examples/hello.cpp

Julia:

https://github.com/JuliaInterop/CxxWrap.jl/blob/master/test/hello.jl

1 Like