C#からC++を呼び出してポインタを使う
C#からC++を呼び出す方法を調べていたのですが、ポインタつかってごにょごにょできることを知って驚きました。 安全に使うには当然いろいろと気をつけなくてはいけないのですが、C++ではここまでできるのかと。
ソースコード
lib.h
の記述
class Value { public: int v; }; typedef void *Handle; extern "C" int CreateValue(Handle *out, int x); extern "C" int AddValue(Handle handle, int x); extern "C" int GetValue(Handle handle, int *out);
lib.cpp
の記述
#include "lib.h" int CreateValue(Handle *out, int v) { *out = new Value{v}; return 0; } int AddValue(Handle handle, int v) { auto p = static_cast<Value*>(handle); p->v += v; return 0; } int GetValue(Handle handle, int *out) { auto p = static_cast<Value*>(handle); *out = p->v; return 0; }
main.cs
の記述
ポイントは以下のとおり:
using System; using System.Runtime.InteropServices; class Program { static void Main(string[] args) { External.CreateValue(out var ptr, 10000); int v; External.GetValue(ptr, out v); Console.WriteLine(v); for (int i = 0; i < 5; i++) { External.AddValue(ptr, 100); External.GetValue(ptr, out v); Console.WriteLine(v); } // おそらくメモリリークしている } } static class External { private const string Path = "../../../lib.so"; [DllImport(Path)] public static extern int CreateValue(out IntPtr ptr, int v); [DllImport(Path)] public static extern int AddValue(IntPtr ptr, int v); [DllImport(Path)] public static extern int GetValue(IntPtr ptr, out int v); }
参考文献
アンマネージ コードとの相互運用
xgboostのAPI
実際ちゃんと使うのであれば、xgboostが行っているようにさまざまな用心をする必要がありそうです。