2010-12-07 19 views
20

He pasado un tiempo jugando con Clojure-CLR. Mi REPL está funcionando, puedo llamar a las clases de .NET de Clojure, pero no he podido descifrar la invocación de los dlls Clojure compilados de las clases de C#.Llamando a Clojure desde .NET

He estado tratando de adaptar el ejemplo java encontró here:

Quité el: línea del nombre de la parte superior del ejemplo, ya que causa una "clave duplicados: nombre:" error. Sin la línea ": name", el código compila bien y puedo agregar la referencia en Visual Studio, pero parece que no puedo entender cómo usar el código. He intentado una variedad de declaraciones de 'uso', pero hasta ahora nada ha funcionado. ¿Alguien puede darnos una pequeña idea sobre esto? Aquí está el código de Clojure que intento usar.

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

Respuesta

15

que era capaz de conseguir que funcione la siguiente manera:

Primero cambió su código un poco, yo estaba teniendo problemas con el espacio de nombres y el compilador pensando que los puntos eran directorios. Así que terminé con esto.

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

A continuación he recopilado llamando:

Clojure.Compile.exe hello

Esto crea varios archivos: hello.clj.dll, hello.clj.pdb, hello.exe y hello.pdb Puede Ejecute hello.exe y debería ejecutar la función -main.

A continuación, creé una aplicación simple de consola C#. Luego añade las siguientes referencias: Clojure.dll, hello.clj.dll y hello.exe

Este es el código de la aplicación de consola:

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(); 
     } 
    } 
} 

Como se puede ver, usted debe ser capaz para crear y usar la clase hello, reside en el ensamblaje hello.exe. No sé por qué la función "salida" no es estática, supongo que es un error en el compilador CLR. También tuve que usar la versión 1.2.0 de ClojureCLR ya que la última vez que lanzaba el ensamblado no encontró excepciones.

Para ejecutar la aplicación, asegúrese de establecer la variable de entorno clojure.load.path donde residen sus binarios Clojure.

Espero que esto ayude.

12

Discutiría que debería tomar otro rumbo en esto. Todas las cosas de clase ejecutiva solo existen en clojure como un truco para decirle al compilador cómo generar clases envoltura Java/C# alrededor de las variables clojure reflective-dynamic nativas.

Creo que es mejor hacer todas las cosas de "clase" en C# y mantener su código de clojure más nativo. Tu elección.Pero si quieres ir por este camino, escribir un envoltorio de la siguiente manera:

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

De esa manera su C# puede parecer normal de C#

 
using System; 

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

Y el clojure puede parecerse clojure normales:

(ns code.clojure.example.hello) 

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

Esto funcionará tanto si lo compila como si lo deja como un script. (RT.load ("hello") cargará el script hello.clj si existe, o de lo contrario cargará el ensamblado hello.clj.dll).

Esto permite que su dispositivo se vea como clojure y su C# se vea como C#. Además, elimina el error del compilador de interoperabilidad del método estático Clojure (y cualquier otro error de interoperabilidad que pueda existir), ya que está eludiendo por completo el compilador de interoperabilidad de clojure.

+0

+1. Me gusta este enfoque y estoy de acuerdo con su razonamiento. También algo se siente mal sobre la vinculación a un EXE. – harpo