Подтвердить что ты не робот

Вызов Clojure из .NET.

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

Я пытаюсь адаптировать пример java, найденный здесь:

Я удалил строку: 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))
4b9b3361

Ответ 1

Мне удалось заставить его работать, выполняя следующие действия:

Сначала я немного изменил код, у меня были проблемы с пространством имен, и компилятор думал, что точки - это каталоги. Поэтому я закончил с этим.

(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.

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

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

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

Ответ 2

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

Я думаю, что лучше всего использовать все "класс" в С# и сохранить код 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));
        }
    }
}

Таким образом, ваш С# может выглядеть как обычный С#

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))

Это будет работать, если вы скомпилируете его или просто оставьте его как script. (RT.load( "hello" ) загрузит script hello.clj, если он существует, или иначе он загрузит сборку hello.clj.dll).

Это позволяет вашему clojure выглядеть как clojure, а ваш С# - как С#. Кроме того, он устраняет статический метод clojure ошибка компилятора interop (и любые другие ошибки interop, которые могут существовать), поскольку вы полностью обходите компилятор clojure interop.