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