Hi I want to use the special functions of Julia implementation (https://juliamath.github.io/SpecialFunctions.jl/dev/functions_list/) inside c++.
Following the manual (https://docs.julialang.org/en/v1/manual/embedding/) I could not achieve so far.
For functions like sqrt
we have something like
jl_function_t *func1 = jl_get_function(jl_base_module,"sqrt");
In a similar fashion what is the module
for these special functions?
I tried to use
jl_function_t *func2 = jl_get_function(jl_specialfunctions_module,"polygamma");
which shows the following error:
signal (11): Segmentation fault
in expression starting at none:0
jl_mutex_wait at /buildworker/worker/package_linux64/build/src/locks.h:24 [inlined]
jl_mutex_lock at /buildworker/worker/package_linux64/build/src/locks.h:94 [inlined]
jl_get_binding_ at /buildworker/worker/package_linux64/build/src/module.c:280
jl_get_global at /buildworker/worker/package_linux64/build/src/module.c:561
jl_get_function at ./test (unknown line)
main at ./test (unknown line)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
_start at ./test (unknown line)
Allocations: 2544 (Pool: 2535; Big: 9); GC: 0
It is not clear from the manual how one should use these special functions in c++. Any lead would be much appreciated!
I found that this was already asked by Federico (particularly for polygamma
): (How to call a julia method defined in an imported package from c++?):
Here is the example:
#include<iostream>
#include<julia.h>
JULIA_DEFINE_FAST_TLS() ;
int main(){
jl_init();
jl_eval_string("print(sqrt(2.0))"); // see that Julia works
jl_module_t* jl_specialfunctions_module = (jl_module_t*)
jl_get_binding(jl_main_module, jl_symbol("SpecialFunctions"));
jl_function_t* func2 = jl_get_function(jl_specialfunctions_module,"polygamma");
jl_value_t *argument1 = jl_box_int64(1);
jl_value_t *argument2 = jl_box_float64(2.0);
jl_value_t *arguments[2] = { argument1 , argument2 };
jl_value_t *ret = jl_call(func2, arguments, 2);
if (jl_typeis(ret, jl_float64_type)) {
double ret_unboxed = jl_unbox_float64(ret);
std::cout << "julia = " << ret_unboxed << std::endl;
}
else {
std::cout << "Error" << std::endl;
}
jl_atexit_hook(0);
return 0;
}
No answer there unfortunately!
Similar happens when I try to adapt this: https://discourse.julialang.org/t/jl-get-function-throwing-segmentation-fault/37186
NB: The special functions extension was installed through import Pkg; Pkg.add("SpecialFunctions")
and in the julia
shell the special functions are accessible.
Functions in Julia can be combined by composing or piping (chaining) them together. Function composition is when you combine functions together and apply the resulting composition to arguments. You use the function composition operator ( ∘ ) to compose the functions, so (f ∘ g)(args...) is the same as f(g(args...)) .
To allow easy use of this existing code, Julia makes it simple and efficient to call C and Fortran functions. Julia has a "no boilerplate" philosophy: functions can be called directly from Julia without any "glue" code, code generation, or compilation – even from the interactive prompt.
Method Tables Every function in Julia is a generic function. A generic function is conceptually a single function, but consists of many definitions, or methods. The methods of a generic function are stored in a method table. Method tables (type MethodTable ) are associated with TypeName s.
It is a purely syntactical transformation. if you will, i.e. the do block defines an anonymous function that is passed as the first argument. For this to work it is, of course, required that there exist a method of func that has a matching signature, for example func(f::Function, ...)
This may sound like a strange restriction, but remember that since C is not a dynamic language like Julia, its functions can only accept argument types with a statically-known, fixed signature.
The basic syntax for defining functions in Julia is: julia> function f (x,y) x + y end f (generic function with 1 method) This function accepts two arguments x and y and returns the value of the last expression evaluated, which is x + y. There is a second, more terse syntax for defining a function in Julia.
Without parentheses, the expression f refers to the function object, and can be passed around like any other value: As with variables, Unicode can also be used for function names: Julia function arguments follow a convention sometimes called "pass-by-sharing", which means that values are not copied when they are passed to functions.
For instance, when developing C code for use with Julia, one may need to compile, call the C code from Julia, then close the library, make an edit, recompile, and load in the new changes. One can either restart Julia or use the Libdl functions to manage the library explicitly, such as:
I answered this question in the other stackoverflow thread.
Basically, the easiest thing to do is to use the Julia @cfunction
construct to let Julia compile the code into a C++ function pointer, which you can then call normally without worrying about unboxing etcetera.
(For passing complex numbers, @cfunction
can exploit the fact that C++ std::complex<double>
and Julia Complex{Float64}
have identical memory representations.)
Thanks to @Matt B, I looked into Julia codes and see how these modules are there. So the following could be one possible solution.
#include <julia.h>
#include<iostream>
JULIA_DEFINE_FAST_TLS()
int main(){
jl_init();
jl_eval_string("using SpecialFunctions");
jl_module_t* SpecialFunctions =(jl_module_t*)jl_eval_string("SpecialFunctions");
jl_function_t *func2 = jl_get_function(SpecialFunctions, "polygamma");
// arguments to pass to polygamma
jl_value_t *argument1 = jl_box_int64(1);
jl_value_t *argument2 = jl_box_float64(2.0);
jl_value_t *arguments[2] = { argument1 , argument2 };
jl_value_t *ret2 = jl_call(func2, arguments, 2);
if (jl_typeis(ret2, jl_float64_type)){
double ret_unboxed = jl_unbox_float64(ret2);
std::cout << "\n julia result = " << ret_unboxed << std::endl;
}
else{
std::cout<<"hello error!!"<<std::endl;
}
jl_atexit_hook(0);
return 0;
}
Now I need to see how can I pass complex numbers to the argument of polygamma
which is why all these fuss about :) !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With