2010-12-07 2 views
20

Я проводил некоторое время, играя с Clojure-CLR. Мой REPL работает, я могу назвать классы .NET из Clojure, но мне не удалось вычислить вызов скомпилированных библиотек Clojure из классов C#.Вызов Clojure из .NET

Я пытался адаптировать пример 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.exe. Я не потому, что функция «output» не является статической, я предполагаю, что это ошибка в компиляторе CLR. Я также должен был использовать версию ClojureCLR версии 1.2.0, поскольку последняя из них собирала не найденные исключения.

Чтобы выполнить приложение, убедитесь, что переменная среды clojure.load.path установлена ​​там, где находятся ваши двоичные файлы Clojure.

Надеюсь, это поможет.

12

Я бы поспорил, что вы должны принять еще одно решение. Все эти вещи gen-class существуют только в clojure как хак, чтобы сообщить компилятору, как создавать классы оболочки Java/C# вокруг собственных отражающих динамических переменных clojure.

Я думаю, что лучше всего использовать все «классные» вещи на 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 interop compiler bug (и любые другие ошибки interop, которые могут существовать), поскольку вы полностью обходите компилятор clojure interop.

+0

+1. Мне нравится этот подход и согласен с вашими рассуждениями. Также что-то кажется неправильным в отношении ссылки на EXE. – harpo 2013-01-15 23:23:39

Смежные вопросы