将Julia脚本嵌入C#:jl_get_function不存在?

时间:2017-06-01 18:01:34

标签: c# unity3d pinvoke julia

目前我正在开发一个项目,我必须在Unity中从C#调用其他人编写的一些Julia脚本。我一直试图做一些基本的例子,看看哪些有效,哪些无效。在Julia文档中,它说使用函数:jl_get_function来获取指向具有julia模块的函数的指针。但是,我在EntryPointNotFound中获得了libjulia.dll,当我使用DependencyWalker在我的计算机上打开dll时,我找不到一个名为该函数的函数。我疯了还是安装了奇怪的东西? jl_eval_stringjl_unbox_float64等其他内容正常。

另外,我不完全确定如何获得jl_get_function模块的指针。我曾想过从内存映射文件对象中抓取一个指针,或从IntPtr抓取jl_eval_string(include([module name in directory]));,但我不确定。

这是我在Julia进行此测试的代码。

module TestModule

export calculate

function calculate(a::Float64,b::Float64)::Float64
  return 3a+b^2
end
function calcMore(a,b)
  return ones(a,b)::Array{Float64,2};
end
function moreTest(a::Float64, b::Float64)
  return (a+b)::Float64;
end
end

这是我在C#中的代码,这已被剪掉了一些

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace TestCInCSharp
{
class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetDllDirectory(string lpPathName);

    [DllImport("libjulia.dll", SetLastError = true)]
    public static extern void jl_init(string path);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr jl_eval_string(string input);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr jl_box_float64(float value);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern double jl_unbox_float64(IntPtr value);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr jl_get_function(IntPtr func, string name);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr jl_call2(IntPtr func, IntPtr v1, IntPtr v2);

    [DllImport("libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void jl_atexit_hook(int a);

    static void Main(string[] args)
    {
        string p = @"C:\Users\schulk4\Documents\Programming\TestJuliaSim\Assets\test_julia.jl";
        string julia_path = @"C:\Users\schulk4\AppData\Local\Julia-0.5.2\bin";
        IntPtr module, module2;
        IntPtr a, b, c;

        SetDllDirectory(julia_path);
        jl_init(julia_path);
        p = @"C:\\Users\\schulk4\\Documents\\Programming\\TestJuliaSim\\Assets\\test_julia.jl";
        p = "include(\"" + p + "\")";
        module = jl_eval_string(p); //holds module pointer?
        a = jl_eval_string("TestModule.calculate(3.0,4.0)");
        double d = jl_unbox_float64(a);
        Console.WriteLine(d);
        a = jl_eval_string("TestModule.calculate");
        b = jl_box_float64(3.0f);
        c = jl_box_float64(4.0f);
        module2 = jl_call2(a, b, c);
        d = jl_unbox_float64(module2);
        Console.WriteLine(d);

        a = jl_eval_string("TestModule.moreTest");
        b = jl_box_float64(12.0f);
        c = jl_box_float64(13.0f);
        module2 = jl_call2(a, b, c);
        d = jl_unbox_float64(module2);
        Console.WriteLine(d);

        IntPtr f = jl_get_function(module, "calculate"); //EntryPointNotFoundException

        jl_atexit_hook(0);
        Console.ReadLine();
    }
}

}

您可以看到我尝试在代码中使用jl_eval_string获取指向函数的指针。这是在异常之前运行的示例:

25
1.5977136277678E-314
1.08223857600744E-314

我遇到了各种各样的问题,我只是想知道是否有人能够帮助我。我对这个主题不太熟悉,大约一周前我了解了P/Invoke

1 个答案:

答案 0 :(得分:1)

jl_get_function是一个内联函数。您可以使用jl_get_global

另请注意,您的代码可能随时崩溃。需要在调用julia运行时/函数时使用的所有jl_value_t*必须是root。请参阅嵌入文档中的内存管理部分。我不知道你怎么把它翻译成C#。