从.NET调用Clojure

tlt*_*tjr 20 .net clojure clojureclr

我一直在和Clojure-CLR一起玩.我的REPL正在工作,我可以从Clojure调用.NET类,但我无法弄清楚从C#类调用编译的Clojure dll.

我一直在尝试调整这里找到的java示例:

我从示例顶部删除了:name行,因为它导致"Duplicate key :: name"错误.没有":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))
Run Code Online (Sandbox Code Playgroud)

Tro*_*oyC 16

我能够让它按照以下方式工作:

首先我改变了你的代码,我在命名空间和编译器认为点是目录时遇到了麻烦.所以我最终得到了这个.

(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))))
Run Code Online (Sandbox Code Playgroud)

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

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,您应该能够创建和使用hello类,它位于hello.exe程序集中.我不是函数"output"不是静态的原因,我认为它是CLR编译器中的一个错误.我还不得不使用1.2.0版本的ClojureCLR作为最新的抛出程序集未找到异常.

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

希望这可以帮助.


Dax*_*ohl 13

我认为你应该采取另一种措施.所有gen-class东西只存在于clojure中作为hack告诉编译器如何围绕本机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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样你的C#看起来就像普通的C#

using System;

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

而且clojure看起来像普通的clojure:

(ns code.clojure.example.hello)

(defn output [a b]
  (+ a b))
Run Code Online (Sandbox Code Playgroud)

无论您是编译它还是将其保留为脚本,这都将起作用.(RT.load("hello")将加载脚本hello.clj(如果存在),否则它将加载hello.clj.dll程序集.

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