20

私は Clojure-CLR で遊んでいます。私の REPL は機能しており、Clojure から .NET クラスを呼び出すことはできますが、コンパイルされた Clojure DLL を C# クラスから呼び出すことはできませんでした。

ここにあるJavaの例を適応させようとしています:

「Duplicate key: :name」エラーが発生するため、例の先頭から :name 行を削除しました。":name" 行がなければ、コードは正常にコンパイルされ、Visual Studio で参照を追加できますが、コードの使用方法がわかりません。さまざまな「using」ステートメントを試しましたが、これまでのところ何も機能していません。誰でもこれについて少し洞察を提供できますか? これが私が使用しようとしている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))
4

2 に答える 2

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

次に、次のように呼び出してコンパイルしました。

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アセンブリにあります。関数「output」が静的でない理由ではありません。CLRコンパイラのバグだと思います。また、ClojureCLRの1.2.0バージョンを使用する必要がありました。これは、最新のスローアセンブリが例外を検出しなかったためです。

アプリケーションを実行するには、clojure.load.path環境変数をClojureバイナリが存在する場所に設定してください。

お役に立てれば。

于 2010-12-09T02:51:18.497 に答える
14

私はあなたがこれについて別のタックをとるべきだと主張します. 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 相互運用コンパイラを完全に回避しているため、静的メソッド clojure 相互運用コンパイラのバグ (および存在する可能性のあるその他の相互運用バグ) が排除されます。

于 2010-12-30T06:57:20.273 に答える