【问题标题】:Calling local Julia package from C从 C 调用本地 Julia 包
【发布时间】:2019-05-07 18:08:29
【问题描述】:

Julia 文档展示了如何从 C 调用 Base Julia 函数的示例(例如 sqrt),我已经成功地复制了这些函数。我真正感兴趣的是调用本地开发的 Julia 模块,并且从文档中根本不清楚如何调用非 Base 函数。几年前有一些关于这个问题的讨论线程,但 API 似乎在此期间发生了变化。任何指针将不胜感激。

【问题讨论】:

  • 我不认识 Julia,但Creating C-Compatible Julia Function Pointers 部分可以提供帮助吗?您可能必须从 Julia 开始,以便将一个或多个 @cfunction 调用的结果传递给 C,以便您的 C 代码可以在以后调用 Julia 函数。
  • @TripeHound 不幸的是,我的用例涉及从 C 内部构建和拆除 Julia。
  • 您是否检查过以下说明docs.julialang.org/en/v1/manual/embedding 是否适合您?特别是,您是否尝试将字符串传递给 jl_eval_string 函数,该函数首先加载非基本模块,然后执行您需要执行的内容,或者甚至 - 在极端情况下传递 include("path_to_Julia_script_that does_all_the_required_work")
  • @BogumiłKamiński 是的,我在发布我的问题之前尝试了所有这些。 jl_eval_string 返回一个 NULL 指针。
  • 能否请您准确发布您的代码。

标签: c julia


【解决方案1】:

jl_eval_string("using SomeModule") 返回NULL 的原因仅仅是因为using SomeModule 返回nothing

您可以通过首先导入模块来使用其他模块中的函数,然后将 Julia 模块中的函数对象检索到 C 中。例如,让我们使用包 GR 及其 plot 函数。我们可以通过

获得plot函数
jl_eval_string("using GR") // this returns nothing
jl_module_t* GR = (jl_module_t *)jl_eval_string("GR") // this returns the module

/* get `plot` function */
jl_function_t *plot = jl_get_function(GR, "plot");

这里我们将GR 模块作为第一个参数传递给jl_get_function。我们可以,知道事情将被加载到模块Mainplot 是从GR 导出的事实,使用下面的sn-p 来代替做同样的事情。请注意,jl_main_module 包含一个指向模块 Main 的指针。

jl_eval_string("using GR")

/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "plot");

我们也可以使用plots 限定名。

/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "GR.plot");

也就是说,这里是使用GR 绘制值数组的完整示例。该示例使用第一种样式来获取函数GR.plot

#include <julia.h>

JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.

#include <stdio.h>

int main(int argc, char *argv[])
{
    /* required: setup the Julia context */
    jl_init();

    /* create a 1D array of length 100 */
    double length = 100;
    double *existingArray = (double*)malloc(sizeof(double)*length);

    /* create a *thin wrapper* around our C array */
    jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
    jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);

    /* fill in values */
    double *xData = (double*)jl_array_data(x);
    for (int i = 0; i < length; i++)
        xData[i] = i * i;

    /* import `Plots` into `Main` module with `using`*/
    jl_eval_string("using GR");
    jl_module_t* GR = (jl_module_t *)jl_eval_string("GR");;

    /* get `plot` function */
    jl_function_t *plot = jl_get_function(GR, "plot");

    /* create the plot */
    jl_value_t* p = jl_call1(plot, (jl_value_t*)x);


    /* display the plot */
    jl_function_t *disp = jl_get_function(jl_base_module, "display");
    jl_call1(disp, p);

    getchar();

    /* exit */
    jl_atexit_hook(0);
    return 0;
}

从本地文件中包含一个 Julia 模块并在 C 中使用它

我不知道本地 Julia 包的确切含义,但是,您可以 include 您的文件,然后导入这些文件中的模块以执行相同的操作。这是一个示例模块。

# Hello.jl
module Hello
export foo!

foo!(x) = (x .*= 2) # multiply entries of x by 2 inplace

end

要包含此文件,您需要使用jl_eval_string("Base.include(Main, \"Hello.jl\")");。由于某种原因,嵌入式 Julia 无法直接访问 include。您需要改用Base.include(Main, "/path/to/file")

jl_eval_string("Base.include(Main, \"Hello.jl\")");
jl_eval_string("using Main.Hello"); // or just '.Hello'
jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello"); // or just .Hello

这是 C 语言的完整示例。

#include <julia.h>

JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.

#include <stdio.h>

int main(int argc, char *argv[])
{
    /* required: setup the Julia context */
    jl_init();

    /* create a 1D array of length 100 */
    double length = 100;
    double *existingArray = (double*)malloc(sizeof(double)*length);

    /* create a *thin wrapper* around our C array */
    jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
    jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
    JL_GC_PUSH1(&x);
    /* fill in values */
    double *xData = (double*)jl_array_data(x);
    for (int i = 0; i < length; i++)
        xData[i] = i * i;

    /* import `Hello` module from file Hello.jl */
    jl_eval_string("Base.include(Main, \"Hello.jl\")");
    jl_eval_string("using Main.Hello");
    jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello");

    /* get `foo!` function */
    jl_function_t *foo = jl_get_function(Hello, "foo!");

    /* call the function */
    jl_call1(foo, (jl_value_t*)x);

    /* print new values of x */
    for (int i = 0; i < length; i++)
        printf("%.1f ", xData[i]);

    printf("\n");
    JL_GC_POP();

    getchar();

    /* exit */
    jl_atexit_hook(0);
    return 0;
}

【讨论】:

  • 很抱歉花了这么长时间来奖励赏金 - 我认为接受答案会自动奖励它。
猜你喜欢
  • 2020-06-15
  • 1970-01-01
  • 2022-01-22
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2015-08-13
相关资源
最近更新 更多