Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Julia special functions inside c++

Tags:

c++

julia

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.

like image 735
Boogeyman Avatar asked Dec 16 '20 11:12

Boogeyman


People also ask

How do you use functions in Julia?

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...)) .

Can Julia call C?

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.

What is a generic function Julia?

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.

Does Julia have syntax?

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, ...)

Why can’t I use Julia’s functions in C?

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.

How do you write a function in Julia?

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.

What does the expression f mean 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.

How do I compile and load C code in Julia?

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:


2 Answers

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.)

like image 123
SGJ Avatar answered Oct 25 '22 22:10

SGJ


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 :) !

like image 35
Boogeyman Avatar answered Oct 25 '22 23:10

Boogeyman