Hi guys!
I just want to share a very simple code I created in C++ (using standard C++14) to make calls to Julia functions easier. My use case is that I need to call a lot of functions from my package SatelliteToolbox.jl and all the values are handle by the C++. Hence, there is not reuse of packed variables, i.e., no concerns about GC.
The code I am using (please, let me know if I am making something bad) is:
#include <iostream>
#include <string>
#include <vector>
extern "C" {
#include <julia.h>
}
void pack_jl_vars(jl_value_t** args_jl, int v) {
*args_jl = jl_box_int64(v);
}
void pack_jl_vars(jl_value_t** args_jl, double v) {
*args_jl = jl_box_float64(v);
}
template<typename T, typename... Ts>
void pack_jl_vars(jl_value_t** args_jl, T v, Ts... s)
{
pack_jl_vars(args_jl, v);
pack_jl_vars(args_jl + 1, s...);
}
template<typename... Targs>
jl_value_t* jl_call(jl_function_t* func_jl, Targs... args) {
int nargs = sizeof...(args);
jl_value_t** args_jl;
jl_value_t* ret;
JL_GC_PUSHARGS(args_jl, nargs);
pack_jl_vars(args_jl, args...);
ret = (jl_value_t*)jl_call(func_jl, args_jl, nargs);
JL_GC_POP();
return ret;
}
template<typename... Targs>
jl_value_t* jl_call(std::string func_str, Targs... args) {
jl_function_t* func_jl = jl_get_function(jl_base_module, func_str.c_str());
return jl_call(func_jl, args...);
}
In this case, I can call any Julia function in jl_base_module
by just:
jl_value_t* ret = jl_call("+", M_PI, 3.0, 2.0, 1.0, 1);
This code is handling only integers and floats, but can easily be expanded by adding more overloads to pack_jl_vars
.