Monoの言語(C#、Boo、etc.)をスクリプティングとして使う場合とかに使える、C++の小さいサンプル。
このサンプルでは「C++→スクリプト」と「スクリプト→C++」の2方向の呼び出しを試している。
「C++→スクリプト」はMonoのAPI (mono_runtime_invokeとか) をつかってがんばる。「スクリプト→C++」はP/Invokeを使えばできる。
$ 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アプリケーション>
#include <mono/jit/jit.h> #include <mono/metadata/assembly.h> #include <mono/metadata/debug-helpers.h> #include <mono/metadata/mono-config.h> #include <string> #include <iostream> #include <stdlib.h> #include <stdio.h> #ifdef _MSC_VER # define EXPORT_FUNC extern __declspec(dllexport) #else # include <dlfcn.h> # 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; } } }