2010-12-07 90 views
20

我一直在玩Clojure-CLR。我的REPL工作正常,我可以从Clojure调用.NET类,但是我一直无法从C#类中调用编译的Clojure dll。从.NET调用Clojure

我一直在努力适应Java示例发现here:

我删除了:从示例上方的姓名线,因为它会导致“重复键:名称”的错误。没有“:name”这一行,代码编译得很好,我可以在Visual Studio中添加引用,但我似乎无法弄清楚如何使用代码。我已经尝试了各种'使用'语句,但迄今没有任何工作。任何人都可以提供一些关于此的见解吗?这是我尝试使用的Clojure代码。

(ns code.clojure.example.hello 
    (:gen-class 
    :methods [#^{:static true} [output [int int] int]])) 

(defn output [a b] 
    (+ a b)) 

(defn -output 
    [a b] 
    (output a b)) 

回答

15

我能得到它的工作执行以下操作:

首先,我改变了你的代码了一下,我是有命名空间的麻烦和编译器思考点是目录。所以我结束了这一点。

(ns hello 
    (:require [clojure.core]) 
    (:gen-class 
    :methods [#^{:static true} [output [int int] int]])) 

(defn output [a b] 
    (+ a b)) 

(defn -output [a b] 
    (output a b)) 

(defn -main [] 
    (println (str "(+ 5 10): " (output 5 10)))) 

接下来,我通过调用编译它:

Clojure.Compile.exe hello

此创建一些文件:hello.clj.dll,hello.clj.pdb,用hello.exe和hello.pdb你可以执行hello.exe,它应该运行-main函数。

接下来我创建了一个简单的C#控制台应用程序。然后,我添加了以下参考:Clojure.dll,hello.clj.dll,并用hello.exe

这里是控制台应用程序的代码:

using System; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      hello h = new hello(); 
      System.Console.WriteLine(h.output(5, 9)); 
      System.Console.ReadLine(); 
     } 
    } 
} 

正如你所看到的,你应该能够要创建和使用hello类,它驻留在hello.exe程序集中。我不是为什么函数“输出”不是静态的,我认为这是CLR编译器中的一个错误。我也不得不使用ClojureCLR的1.2.0版本作为最新的抛出程序集,没有发现异常。

为了执行应用程序,请确保将clojure.load.path环境变量设置为Clojure二进制文件所在的位置。

希望这会有所帮助。

12

我认为你应该采取另一个方法来解决这个问题。所有那些gen-class的东西只存在于clojure中,作为一种黑客来告诉编译器如何围绕本地clojure反射动态变量生成包装Java/C#类。

我认为最好在C#中做所有的“类”东西,并保持clojure代码更加本地化。你的选择。但是,如果你想要走这条路,写这样的包装:

 
using System; 
using clojure.lang; 

namespace ConsoleApplication { 
    static class Hello { 
     public static int Output(int a, int b) { 
      RT.load("hello"); 
      var output = RT.var("code.clojure.example.hello", "output"); 
      return Convert.ToInt32(output.invoke(a, b)); 
     } 
    } 
} 

这样,你的C#可以像普通的C#

 
using System; 

namespace ConsoleApplication { 
    class Program { 
     static void Main() { 
      Console.WriteLine("3+12=" + Hello.Output(3, 12)); 
      Console.ReadLine(); 
     } 
    } 
} 

而且Clojure中可以像正常的Clojure:

(ns code.clojure.example.hello) 

(defn output [a b] 
    (+ a b)) 

无论你编译它还是把它作为脚本,这都会起作用。 (RT.load(“hello”)将加载脚本hello.clj(如果它存在),否则它将加载hello.clj.dll程序集)。

这使您的clojure看起来像clojure和C#看起来像C#。此外,它消除了静态方法clojure互操作编译器错误(以及可能存在的其他任何互操作错误),因为您完全绕过了clojure互操作编译器。

+0

+1。我喜欢这种方法,并赞同你的推理。还有一些关于链接到EXE的感觉错误。 – harpo 2013-01-15 23:23:39