====== Monoの組み込み ====== Monoの言語(C#、Boo、etc.)をスクリプティングとして使う場合とかに使える、C++の小さいサンプル。 このサンプルでは「C++→スクリプト」と「スクリプト→C++」の2方向の呼び出しを試している。 「C++→スクリプト」はMonoのAPI (mono_runtime_invokeとか) をつかってがんばる。「スクリプト→C++」はP/Invokeを使えばできる。 ===== 動作環境 ===== * LinuxでもWindowsでも動くはず。。。 * 当然Monoが正しくインストールされている必要はある ==== 確認環境 ==== * Gentoo Linux * Linux Kernel 32bit * Mono 2.8.2 ===== ビルド方法 ===== $ booc test_boo.boo $ dmcs test_cs.cs $ g++ -export-dynamic -g monotest.cpp -o monotest `pkg-config --cflags --libs mono-2` ===== 使用方法 ===== $ ./monotest lib <テスト用アセンブリ> $ ./monotest app <.NETアプリケーション> * <テスト用アセンブリ>には、ビルドしたtest_booやtest_csの名前をいれる。 * <.NETアプリケーション>にはMonoで動作する任意の.NETアプリケーションを与えられるはず。。。 ===== ソースコード ===== ==== ホストプログラム ==== #include #include #include #include #include #include #include #include #ifdef _MSC_VER # define EXPORT_FUNC extern __declspec(dllexport) #else # include # define EXPORT_FUNC #endif using namespace std; extern "C" { EXPORT_FUNC void PrintFunc(int val); } void error(const string &msg = "") { cerr << "Error:" << msg << endl; abort(); } int main(int argc, char* argv[]) { int retval; #ifndef _MSC_VER // Export Check void *ThisModule = dlopen(NULL, RTLD_LAZY); cout << "Module Handle:" << ThisModule << endl; void *pFunc = dlsym(ThisModule, "PrintFunc"); cout << "Function Handle:" << pFunc << endl; if(!pFunc) error("No symbol: PrintFunc"); // mono_set_dirs("./monolib","./monoetc"); #else mono_set_dirs(".\\monolib",".\\monoetc"); #endif MonoDomain *domain; if (argc < 3){ fprintf (stderr, "Please provide an assembly to load\n"); return 1; } string cmd = argv[1]; string file = argv[2]; mono_config_parse(NULL); domain = mono_jit_init("monotest"); if(cmd == "lib") { MonoAssembly *assembly = mono_domain_assembly_open (domain, file.c_str()); if (!assembly) error("No such assembly"); PrintFunc(0); MonoImage *image = mono_assembly_get_image(assembly); MonoClass *klass = mono_class_from_name(image, "TestNamespace", "TestClass"); MonoMethodDesc *desc = mono_method_desc_new(":TestStaticMethod(int)", false); MonoMethod *static_method = mono_method_desc_search_in_class (desc, klass); void *args[1]; int val1 = 1234; args[0] = &val1; mono_runtime_invoke (static_method, NULL, args, NULL); } else { MonoAssembly *assembly = mono_domain_assembly_open (domain, file.c_str()); retval = mono_jit_exec (domain, assembly, argc - 1, argv + 1); } mono_jit_cleanup(domain); return retval; } void PrintFunc(int val) { cout << "In PrintFunc :" << val << endl; } ==== テスト用アセンブリのソース ==== namespace TestNamespace import System.Runtime.InteropServices [DllImport("__Internal", EntryPoint: "PrintFunc")] def PrintFunc(val as int): pass class TestClass: static def TestStaticMethod(val1 as int): print "In TestClass: ", val1 PrintFunc(val1 * 2) return using System; using System.Runtime.InteropServices; namespace TestNamespace{ class TestClass { [DllImport("__Internal")] public static extern void PrintFunc(int v); static void TestStaticMethod(int val1) { Console.WriteLine("In TestClass: "); Console.WriteLine(val1); PrintFunc(val1 * 2); return; } } }