çµ±åã®åé¡ã¯ããã§äœåºŠãçºçããŠããŸãããååãšããŠããããŒãžã³ãŒãã§ã¯å®è£ ã§ããªãããã€ãã®ã¡ãœããã®çµ±åã«å°å¿µããŠããŸãã ç§ãã¡ã®ã¿ã¹ã¯ã¯ãC ++ããã¢ãžã¥ãŒã«ãååŸãã.NETã§åäœãããããšã§ããã ããã€ãã®çç±ã§ãå床æžã蟌ããªãã·ã§ã³ã¯èæ ®ãããªãã£ããããçµ±åãéå§ããŸããã
ãã®èšäºã§ã¯ãã¢ã³ãããŒãžã¢ãžã¥ãŒã«ã.NETã«çµ±åããéã®ãã¹ãŠã®åé¡ãé瀺ããŠããããã§ã¯ãããŸããã æååãè«çå€ãªã©ãæž¡ãããšã«ã¯ãŸã 埮åŠãªéãããããŸãããããã®åé¡ã«é¢ããHabréã«é¢ããããã¥ã¡ã³ããšããã€ãã®èšäºãããããããããã®åé¡ã¯ããã§ã¯èæ ®ããŸããã§ããã
Platform Invokeã«åºã¥ã.NETã©ãããŒã¯ã¯ãã¹ãã©ãããã©ãŒã ã§ãããMono + gccã§ã¢ã»ã³ãã«ã§ããããšã«æ³šæããŠãã ããã
ã·ãŒã«ãã¯ã©ã¹ã®çµ±å
Platform Invokeãšçµ±åãããšãã«æåã«æ°ä»ããªããã°ãªããªãã®ã¯ããã®ããŒã«ã䜿çšãããšç¹å®ã®æ©èœã®ã¿ãçµ±åã§ããããšã§ãã ã¯ã©ã¹ãååŸããŠçµ±åããããšã¯ã§ããŸããã åé¡ã®è§£æ±ºçã¯ç°¡åã«èŠããŸãïŒ
é管çåŽã§ã¯ãé¢æ°ãèšè¿°ããŸãã
SomeType ClassName_methodName(ClassName * instance, SomeOtherType someArgument) { instance->methodName(someArgument); }
ãã®ãããªé¢æ°ã«externâ Câãè¿œå ããŠããããã®ååãC ++ã³ã³ãã€ã©ãŒã§ä¿®é£Ÿãããªãããã«ããŠãã ããã ããã«ããããããã®æ©èœã.NETã«çµ±åã§ããªããªããŸãã
次ã«ãã¯ã©ã¹ã®ãã¹ãŠã®ãããªãã¯ã¡ãœããã«å¯ŸããŠæé ãç¹°ãè¿ããçµæã®é¢æ°ã.NETã§èšè¿°ãããã¯ã©ã¹ã«çµ±åããŸãã çµæã®ã¯ã©ã¹ã¯ç¶æ¿ã§ããªãããã.NETã§ã¯ãã®ãããªã¯ã©ã¹ã¯å°å°æžã¿ãšããŠå®£èšãããŸãã ãã®å¶éãåé¿ããæ¹æ³ãšãããé¢é£ä»ããããŠããããš-以äžãåç §ããŠãã ããã
ãããŸã§ã®éãç°¡åãªäŸã瀺ããŸãã
管çãããŠããªãã¯ã©ã¹ïŒ
class A { int mField; public: A( int someArgument); int someMethod( int someArgument); };
çµ±åã®æ©èœïŒ
A * A_createInstance(int someArgument) { return new A(someArgument); } int A_someMethod(A *instance, int someArgument) { return instance->someMethod( someArgument); } void A_deleteInstance(A *instance) { delete instance; }
.Netã§ã®å®è£ ïŒ
public sealed class A { private IntPtr mInstance; private bool mDelete; [ DllImport( "shim.dll", CallingConvention = CallingConvention .Cdecl)] private static extern IntPtr A_createInstance( int someArgument); [ DllImport( "shim.dll", CallingConvention = CallingConvention .Cdecl)] private static extern int A_someMethod( IntPtr instance, int someArgument); [ DllImport( "shim.dll", CallingConvention = CallingConvention .Cdecl)] private static extern void A_deleteInstance( IntPtr instance); internal A( IntPtr instance) { Debug.Assert(instance != IntPtr.Zero); mInstance = instance; mDelete = false; } public A( int someArgument) { mInstance = A_createInstance(someArgument); mDelete = true; } public int someMethod( int someArgument) { return A_someMethod(mInstance, someArgument); } internal IntPtr getUnmanaged() { return mInstance; } ~A() { if (mDelete) A_deleteInstance(mInstance); } }
ã¢ã³ãããŒãžã³ãŒãããã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãååŸããŠè¿ãã«ã¯ãå éšã³ã³ã¹ãã©ã¯ã¿ãŒãšã¡ãœãããå¿ èŠã§ãã ç¶æ¿ã®åé¡ã¯ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãã¢ã³ãããŒãžç°å¢ã«æ»ãããšã«é¢é£ããŠããŸãã .NETã§ã¯ã©ã¹Aãç¶æ¿ãããã®ã¡ãœããã®æ°ãåå®çŸ©ããå ŽåïŒsomeMethodãvirtualããŒã¯ãŒãã§å®£èšãããŠãããšä»®å®ïŒãã¢ã³ãããŒãžç°å¢ããåå®çŸ©ãããã³ãŒããåŒã³åºãããšã¯ã§ããŸããã

ã€ã³ã¿ãŒãã§ã€ã¹çµ±å
ã€ã³ã¿ãŒãã§ã€ã¹ãçµ±åããã«ã¯ããã£ãŒãããã¯ãå¿ èŠã§ãã ã€ãŸã çµ±åã¢ãžã¥ãŒã«ãå®å šã«äœ¿çšããã«ã¯ããã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããæ©èœãå¿ èŠã§ãã å®è£ ã¯ã管ç察象ç°å¢ã§ã®ã¡ãœããã®å®çŸ©ã«é¢é£ããŠããŸãã ãããã®ã¡ãœããã¯ãã¢ã³ãããŒãžã³ãŒãããåŒã³åºãå¿ èŠããããŸãã ããã§ãPlatform Invokeã®ããã¥ã¡ã³ãã§èª¬æãããŠããã³ãŒã«ããã¯ã¡ãœããã圹ç«ã¡ãŸãã
ç°å¢ã®ç®¡çãããŠããªãåŽã§ã¯ãã³ãŒã«ããã¯ã¯é¢æ°ãžã®ãã€ã³ã¿ãŒãšããŠè¡šç€ºãããŸãã
typedef void (*PFN_MYCALLBACK )(); int _MyFunction(PFN_MYCALLBACK callback);
.NETã§ã¯ãããªã²ãŒãããã®åœ¹å²ãæãããŸãã
[UnmanagedFunctionPointerAttribute( CallingConvention.Cdecl)] public delegate void MyCallback (); [ DllImport("MYDLL.DLL",CallingConvention.Cdecl)] public static extern void MyFunction( MyCallback callback);
ãã£ãŒãããã¯ããŒã«ã䜿çšãããšããªãŒããŒã©ã€ããããã¡ãœãããžã®åŒã³åºããç°¡åã«æäŸã§ããŸãã
ãããã管çãããŠããªãç°å¢ã§ãã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ã®ã€ã³ã¹ã¿ã³ã¹ãæž¡ãã«ã¯ãå®è£ ã®ã€ã³ã¹ã¿ã³ã¹ãšããŠãæ瀺ããå¿ èŠããããŸãã ãããã£ãŠã管çãããŠããªãç°å¢ã§å¥ã®å®è£ ãäœæããå¿ èŠããããŸãã ãšããã§ããã®å®è£ ã§ã¯ãã³ãŒã«ããã¯é¢æ°ãåŒã³åºããŸãã
æ®å¿µãªããããã®ã¢ãããŒãã§ã¯ããããŒãžã€ã³ã¿ãŒãã§ã€ã¹ã§ããžãã¯ãªãã§ã¯å®è¡ã§ããªããããæœè±¡ã¯ã©ã¹ã®åœ¢åŒã§ããžãã¯ãæ瀺ããå¿ èŠããããŸãã ã³ãŒããèŠãŠã¿ãŸãããïŒ
管çãããŠããªãã€ã³ã¿ãŒãã§ãŒã¹ïŒ
class IB { public: virtual int method( int arg) = 0; virtual ~IB() {}; };
管çãããŠããªãå®è£
typedef int (*IB_method_ptr)(int arg); class UnmanagedB : public IB { IB_method_ptr mIB_method_ptr; public: void setMethodHandler( IB_method_ptr ptr); virtual int method( int arg); //... / }; void UnmanagedB ::setMethodHandler(IB_method_ptr ptr) { mIB_method_ptr = ptr; } int UnmanagedB ::method(int arg ) { return mIB_method_ptr( arg); }
UnmanagedBã¡ãœããã¯ããããŒãžã¯ã©ã¹ãæäŸããã³ãŒã«ããã¯ãåŒã³åºãã ãã§ãã ããã§ãã1ã€åé¡ããããŸãã 誰ããã¢ã³ãããŒãžã³ãŒãã§UnmanagedBãžã®ãã€ã³ã¿ãŒãæã£ãŠããéããã³ãŒã«ããã¯åŒã³åºãã«å¿çãããããŒãžã³ãŒãã§ã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãåé€ããæš©å©ã¯ãããŸããã èšäºã®æåŸã®éšåã§ã¯ããã®åé¡ã®è§£æ±ºã«å°å¿µããŸãã
çµ±åã®æ©èœïŒ
UnmanagedB *UnmanagedB_createInstance() { return new UnmanagedB(); } void UnmanagedB_setMethodHandler(UnmanagedB *instance, IB_method_ptr ptr) { instance->setMethodHandler( ptr); } void UnmanagedB_deleteInstance(UnmanagedB *instance) { delete instance; }
ãããŠããããŒãžã³ãŒãã§ã®ã€ã³ã¿ãŒãã§ã€ã¹ã®è¡šçŸã¯æ¬¡ã®ãšããã§ãã
public abstract class AB { private IntPtr mInstance; [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr UnmanagedB_createInstance(); [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr UnmanagedB_setMethodHandler( IntPtr instance, [MarshalAs(UnmanagedType.FunctionPtr)] MethodHandler ptr); [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern void UnmanagedB_deleteInstance( IntPtr instance); [UnmanagedFunctionPointerAttribute( CallingConvention.Cdecl)] private delegate int MethodHandler( int arg); private int impl_method( int arg) { return method(arg); } public abstract int method(int arg); public AB() { mInstance = UnmanagedB_createInstance(); UnmanagedB_setMethodHandler(mInstance, impl_method); } ~AB() { UnmanagedB_deleteInstance(mInstance); } internal virtual IntPtr getUnmanaged() { return mInstance; } }
åã€ã³ã¿ãŒãã§ã€ã¹ã¡ãœããã«ã¯ãã¢ããããŸãã
- åå®çŸ©ãããããªãã¯æœè±¡ã¡ãœãã
- æœè±¡ã¡ãœããïŒæ¥é èŸimplãæã€ãã©ã€ããŒãã¡ãœããïŒã®ãåŒã³åºãå ãã æå³ããªããªãããã«èŠãããããããŸããããããã§ã¯ãããŸããã ãã®ã¡ãœããã«ã¯ãåŒæ°ãšå®è¡çµæã®è¿œå ã®å€æãå«ãŸããå ŽåããããŸãã ãŸããäŸå€ãæž¡ãããã®è¿œå ã®ããžãã¯ãå«ããããšãã§ããŸãïŒãæ³åã®ãšãããç°å¢ããç°å¢ã«äŸå€ãæž¡ãã ãã§ã¯æ©èœããªããããäŸå€ãçµ±åããå¿ èŠããããŸãïŒ
以äžã§ãã ããã§ãã¯ã©ã¹ABãç¶æ¿ãããã®ã¡ãœããmethodããªãŒããŒã©ã€ãã§ããŸãã çžç¶äººãã¢ã³ãããŒãžã³ãŒãã«æž¡ãå¿ èŠãããå Žåã¯ã代ããã«mInstanceãæž¡ããŸããmInstanceã¯ãé¢æ°/ããªã²ãŒããžã®ãã€ã³ã¿ãŒãä»ããŠãªãŒããŒã©ã€ããããã¡ãœãããåŒã³åºããŸãã 管çãããŠããªãç°å¢ããIBã€ã³ã¿ãŒãã§ã€ã¹ãžã®ãã€ã³ã¿ãŒãååŸããå Žåã管çãããç°å¢ã§ã¯ABã€ã³ã¹ã¿ã³ã¹ãšããŠè¡šãå¿ èŠããããŸãã ãããè¡ãã«ã¯ãããã©ã«ãã®ABã®åå«ãå®è£ ããŸãã
internal sealed class BImpl : AB { [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern int BImpl_method( IntPtr instance, int arg); private IntPtr mInstance; internal BImpl( IntPtr instance) { Debug.Assert(instance != IntPtr.Zero); mInstance = instance; } public override int method(int arg) { return BImpl_method(mInstance, arg); } internal override IntPtr getUnmanaged() { return mInstance; } }
çµ±åã®æ©èœïŒ
int BImpl_method(IB *instance , int arg ) { instance->method( arg); }
æŠããŠãããã¯äžèšã®ç¶æ¿ãµããŒãã®ãªãåãã¯ã©ã¹çµ±åã§ãã BImplã€ã³ã¹ã¿ã³ã¹ãäœæãããšãã«ãUnmanagedBã€ã³ã¹ã¿ã³ã¹ãäœæããäžå¿ èŠãªã³ãŒã«ããã¯ãã€ã³ãã£ã³ã°ãäœæããããšã«æ°ä»ãã®ã¯é£ãããããŸããã å¿ èŠã«å¿ããŠããããåé¿ã§ããŸããããããã¯åŸ®åŠãªãããããã§ã¯èª¬æããŸããã

ç¶æ¿ãµããŒããšã®ã¯ã©ã¹çµ±å
ç®æšã¯ãã¯ã©ã¹ãçµ±åãããã®ã¡ãœããããªãŒããŒã©ã€ãããæ©èœãæäŸããããšã§ãã ã¢ã³ãããŒãžã®ã¯ã©ã¹ãžã®ãã€ã³ã¿ãŒãæäŸããããããªãŒããŒã©ã€ããããã¡ãœãããåŒã³åºãããšãã§ããããã«ãã¯ã©ã¹ã«ã³ãŒã«ããã¯ãæäŸããå¿ èŠããããŸãã
ã¢ã³ãããŒãžã³ãŒãã§å®è£ ãããCã¯ã©ã¹ãèããŸãã
class C { public: virtual int method(int arg); virtual ~C() {}; };
ããããããããã€ã³ã¿ãŒãã§ãŒã¹ã§ãããµããããŸãã äžèšã®ããã« ããããçµ±åããŸã ã
管çãããŠããªãã³ãŒã«ããã¯ã®ç¶æ¿è ïŒ
typedef int (*_method_ptr )(int arg); class UnmanagedC : public cpp::C { _method_ptr m_method_ptr; public: void setMethodHandler( _method_ptr ptr); virtual int method( int arg); }; void UnmanagedC ::setMethodHandler(_method_ptr ptr) { m_method_ptr = ptr; } int UnmanagedC ::method(int arg ) { return m_method_ptr( arg); }
çµ±åã®æ©èœïŒ
//... createInstance deleteInstance void UnmanagedC_setMethodHandler(UnmanagedC *instance , _method_ptr ptr ) { instance->setMethodHandler( ptr); }
.Netã§ã®å®è£ ïŒ
public class C { private IntPtr mHandlerInstance; [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr UnmanagedC_setMethodHandler( IntPtr instance, [MarshalAs(UnmanagedType.FunctionPtr)] MethodHandler ptr); [UnmanagedFunctionPointerAttribute( CallingConvention.Cdecl)] private delegate int MethodHandler( int arg); //... / private int impl_method( int arg) { return method(arg); } public virtual int method(int arg) { throw new NotImplementedException(); } public C() { mHandlerInstance = UnmanagedC_createInstance(); UnmanagedC_setMethodHandler(mHandlerInstance, impl_method); } ~C() { UnmanagedC_deleteInstance(mHandlerInstance); } internal IntPtr getUnmanaged() { return mHandlerInstance; } }
ãã®ãããC.methodã¡ãœããããªãŒããŒã©ã€ãã§ããã¢ã³ãããŒãžç°å¢ããæ£ããåŒã³åºãããŸãã ãã ããããã©ã«ãã®å®è£ åŒã³åºãã¯æäŸããŠããŸããã ããã§ã¯ãèšäºã®æåã®éšåã®ã³ãŒãã圹ç«ã¡ãŸãã
ããã©ã«ãã®å®è£ ãåŒã³åºãã«ã¯ããããçµ±åããå¿ èŠããããŸãã ãŸãããã®äœæ¥ã®ããã«ãã¯ã©ã¹ã®é©åãªã€ã³ã¹ã¿ã³ã¹ãå¿ èŠã§ãããäœæããã³åé€ããå¿ èŠããããŸãã 䜿ãæ £ããã³ãŒããååŸããŸãã
//... createInstance deleteInstance int C_method(C *instance, int arg) { return instance->method( arg); }
.Netå®è£ ãçµäºããŸãããã
public class C { //... [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern int C_method(IntPtr instance, int arg); public virtual int method(int arg) { return C_method(mInstance, arg); } public C() { mHandlerInstance = UnmanagedC_createInstance(); UnmanagedC_setMethodHandler(mHandlerInstance, impl_method); mInstance = C_createInstance(); } ~C() { UnmanagedC_deleteInstance(mHandlerInstance); C_deleteInstance(mInstance); } //... }

ãã®ãããªã¯ã©ã¹ã¯ããããŒãžã³ãŒãã§å®å šã«äœ¿çšã§ãããã®ã¡ãœãããç¶æ¿ããªãŒããŒã©ã€ããã¢ã³ãããŒãžç°å¢ã§ã¯ã©ã¹ã«ãã€ã³ã¿ãŒãæž¡ãããšãã§ããŸãã ã¡ãœããããªãŒããŒã©ã€ãããªãã£ãå Žåã§ããUnmanagedCã«ãã€ã³ã¿ãŒãæž¡ããŸãã ã¢ã³ãããŒãžã³ãŒãããããŒãžã³ãŒããä»ããŠã¯ã©ã¹CãããŒããã£ã¹ãåŒã³åºãã®ã¢ã³ãããŒãžã¡ãœãããåŒã³åºãããšãèãããšãããã¯ããŸãåççã§ã¯ãããŸããã ããããããã¯ã¡ãœããããªãŒããŒã©ã€ãããå¯èœæ§ã®ä»£äŸ¡ã§ãã ãã®èšäºã«æ·»ä»ãããŠããäŸã§ã¯ããã®ã±ãŒã¹ã¯ã¯ã©ã¹Dã®ã¡ãœããmethodãåŒã³åºãããšã«ãã£ãŠç€ºãããŠããŸããã³ãŒã«ã¹ã¿ãã¯ãèŠããšã次ã®ã·ãŒã±ã³ã¹ã確èªã§ããŸãã

äŸå€
Platform Invokeã¯äŸå€ã®åãæž¡ããèš±å¯ããŸããããã®åé¡ãåé¿ããããã«ãç°å¢ããç°å¢ã«ç§»åããåã«ãã¹ãŠã®äŸå€ããã£ããããäŸå€ã«é¢ããæ å ±ãç¹å¥ãªã¯ã©ã¹ã«ã©ããããŠæž¡ããŸãã äžæ¹ãåä¿¡ããæ å ±ã«åºã¥ããŠäŸå€ãçæããŸãã
ã©ãããŒã§ãã C ++ã¢ãžã¥ãŒã«ã¯ãModuleExceptionåãŸãã¯ãã®åå«ã®äŸå€ã®ã¿ãã¹ããŒããŸãã ãããã£ãŠããã®äŸå€ãçæã§ãããã¹ãŠã®ã¡ãœããã§ãã®äŸå€ããã£ããããã ãã§ååã§ãã äŸå€ãªããžã§ã¯ãã管çç°å¢ã«ã¹ããŒããã«ã¯ãModuleExceptionã¯ã©ã¹ãçµ±åããå¿ èŠããããŸãã çè«äžãäŸå€ã«ã¯ããã¹ãã¡ãã»ãŒãžãå«ãŸããŠããå¿ èŠããããŸããããã®èšäºã®æååããŒã·ã£ãªã³ã°ã®ãããã¯ã«ç ©ããããããªãã®ã§ãäŸã§ã¯ããšã©ãŒã³ãŒããããããŸãã
public sealed class ModuleException : Exception { IntPtr mInstance; bool mDelete; //... create/delete instance [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern int ModuleException_getCode( IntPtr instance); public int Code { get { return ModuleException_getCode(mInstance); } } public ModuleException( int code) { mInstance = ModuleException_createInstance(code); mDelete = true; } internal ModuleException( IntPtr instance) { Debug.Assert(instance != IntPtr.Zero); mInstance = instance; mDelete = false; } ~ModuleException() { if (mDelete) ModuleException_deleteInstance(mInstance); } //... getUnmanaged }
ããã§ãC ::ã¡ãœãããModuleExceptionãã¹ããŒã§ãããšä»®å®ããŸãã äŸå€ãµããŒãã䜿çšããŠã¯ã©ã¹ãæžãæããŸãã
// , typedef int (*_method_ptr )(int arg, ModuleException **error); int UnmanagedC ::method(int arg ) { ModuleException *error = nullptr; int result = m_method_ptr( arg, &error); if (error != nullptr) { int code = error->getCode(); //... error throw ModuleException(code); } return result; }
int C_method(C *instance, int arg, ModuleException ** error) { try { return instance->method( arg); } catch ( ModuleException& ex) { *error = new ModuleException(ex.getCode()); return 0; } }
public class C { //... [DllImport("shim", CallingConvention = CallingConvention.Cdecl)] private static extern int C_method(IntPtr instance, int arg, ref IntPtr error); [UnmanagedFunctionPointerAttribute( CallingConvention.Cdecl)] private delegate int MethodHandler( int arg, ref IntPtr error); private int impl_method( int arg, ref IntPtr error) { try { return method(arg); } catch (ModuleException ex) { error = ex.getUnmanaged(); return 0; } } public virtual int method(int arg) { IntPtr error = IntPtr.Zero; int result = C_method(mInstance, arg, ref error); if (error != IntPtr.Zero) throw ModuleException(error); return result; } //... }
ããã§ããã¡ã¢ãªç®¡çã«åé¡ããããŸãã impl_methodã¡ãœããã§ã¯ããšã©ãŒãžã®ãã€ã³ã¿ãŒãæž¡ããŸãããã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ã¢ã³ãããŒãžã³ãŒãã§åŠçãããåã«ãããåé€ã§ããŸãã ãã®åé¡ã«å¯ŸåŠããæãæ¥ãŸããïŒ
ã³ãŒã«ããã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒ
ããã§ç§ã¯å€ããå°ãªãã幞éã ãšèšããªããã°ãªããŸããã çµ±åã¢ãžã¥ãŒã«ã®ãã¹ãŠã®ã¯ã©ã¹ãšã€ã³ã¿ãŒãã§ã€ã¹ã¯ãaddRefã¡ãœãããšreleaseã¡ãœãããå«ãç¹å®ã®IObjectã€ã³ã¿ãŒãã§ã€ã¹ããç¶æ¿ãããŸãã ã¢ãžã¥ãŒã«å ã®ãã¹ãŠã®å Žæã§ããã€ã³ã¿ãŒãæž¡ããããšaddRefåŒã³åºããè¡ãããããšãç¥ã£ãŠããŸããã ãããŠããã€ã³ã¿ã®å¿ èŠæ§ããªããªããã³ã«ããªãªãŒã¹ã®åŒã³åºããè¡ãããŸããã ãã®ã¢ãããŒãã«ãããã¢ãžã¥ãŒã«ã«ã¢ã³ãããŒãžãã€ã³ã¿ãŒãå¿ èŠãã©ããããŸãã¯ã³ãŒã«ããã¯ãæ¢ã«åé€ã§ãããã©ãããç°¡åã«è¿œè·¡ã§ããŸãã
管ç察象å€ç°å¢ã§äœ¿çšããã管ç察象ãªããžã§ã¯ãã®åé€ãåé¿ããã«ã¯ããããã®ãªããžã§ã¯ãã®ãããŒãžã£ãŒãå¿ èŠã§ãã addRefãèªã¿åããã¢ã³ãããŒãžã³ãŒãããåŒã³åºãã解æŸãããããŒãžãªããžã§ã¯ããäžèŠã«ãªã£ãã解æŸããŸãã
addRefããã³releaseã®åŒã³åºãã¯ãã¢ã³ãããŒãžã³ãŒããããããŒãžã³ãŒãã«ã¹ããŒããããããæåã«å¿ èŠãªã®ã¯ããã®ãããªè»¢éãæäŸããã¯ã©ã¹ã§ãã
typedef long (*UnmanagedObjectManager_remove )(void * instance); typedef void (*UnmanagedObjectManager_add )(void * instance); class UnmanagedObjectManager { static UnmanagedObjectManager mInstance; UnmanagedObjectManager_remove mRemove; UnmanagedObjectManager_add mAdd; public: static void add( void *instance); static long remove( void *instance); static void setAdd( UnmanagedObjectManager_add ptr); static void setRemove( UnmanagedObjectManager_remove ptr); }; UnmanagedObjectManager UnmanagedObjectManager ::mInstance; void UnmanagedObjectManager ::add(void * instance ) { if (mInstance.mAdd == nullptr) return; mInstance.mAdd( instance); } long UnmanagedObjectManager ::remove(void * instance ) { if (mInstance.mRemove == nullptr) return 0; return mInstance.mRemove( instance); } void UnmanagedObjectManager ::setAdd(UnmanagedObjectManager_add ptr ) { mInstance.mAdd = ptr; } void UnmanagedObjectManager ::setRemove(UnmanagedObjectManager_remove ptr) { mInstance.mRemove = ptr; }
次ã«è¡ãå¿ èŠãããã®ã¯ãaddRefãšIObjectã€ã³ã¿ãŒãã§ã€ã¹ã®ãªãªãŒã¹ãåå®çŸ©ããŠããããŒãžã³ãŒãã«æ ŒçŽãããŠãããããŒãžã£ãŒã®ã«ãŠã³ã¿ãŒå€ãå€æŽããããšã§ãã
template <typename T > class TObjectManagerObjectImpl : public T { mutable bool mManagedObjectReleased; public: TObjectManagerObjectImpl() : mManagedObjectReleased( false) { } virtual ~TObjectManagerObjectImpl() { UnmanagedObjectManager::remove(getInstance()); } void *getInstance() const { return ( void *) this; } virtual void addRef() const { UnmanagedObjectManager::add(getInstance()); } virtual bool release() const { long result = UnmanagedObjectManager::remove(getInstance()); if (result == 0) if (mManagedObjectReleased) delete this; return result == 0; } void resetManagedObject() const { mManagedObjectReleased = true; } };
次ã«ãUnmanagedBã¯ã©ã¹ãšUnmanagedCã¯ã©ã¹ãTObjectManagerObjectImplã¯ã©ã¹ããç¶æ¿ããå¿ èŠããããŸãã UnmanagedCã®äŸãèããŠã¿ãŸãããã
class UnmanagedC : public TObjectManagerObjectImpl <C> { _method_ptr m_method_ptr; public: UnmanagedC(); void setMethodHandler( _method_ptr ptr); virtual int method( int arg); virtual ~UnmanagedC(); };
Cã¯ã©ã¹ã¯IObjectã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããŠããŸãããaddRefã¡ãœãããšreleaseã¡ãœããã¯TObjectManagerObjectImplã¯ã©ã¹ã«ãã£ãŠãªãŒããŒã©ã€ããããããã管çç°å¢ã®ãªããžã§ã¯ããããŒãžã£ãŒã¯ãã€ã³ã¿ãŒã®æ°ãèšç®ããŸãã
ãããŒãžã£ãŒèªèº«ã®ã³ãŒããèŠãŠã¿ãŸãããã
internal static class ObjectManager { //... , , . private static AddHandler mAddHandler; private static RemoveHandler mRemoveHandler; private class Holder { internal int count; internal Object ptr; } private static Dictionary< IntPtr, Holder> mObjectMap; private static long removeImpl( IntPtr instance) { return remove(instance); } private static void addImpl(IntPtr instance) { add(instance); } static ObjectManager() { mAddHandler = new AddHandler(addImpl); UnmanagedObjectManager_setAdd(mAddHandler); mRemoveHandler = new RemoveHandler(removeImpl); UnmanagedObjectManager_setRemove(mRemoveHandler); mObjectMap = new Dictionary<IntPtr , Holder >(); } internal static void add(IntPtr instance, Object ptr = null) { Holder holder; if (!mObjectMap.TryGetValue(instance, out holder)) { holder = new Holder(); holder.count = 1; holder.ptr = ptr; mObjectMap.Add(instance, holder); } else { if (holder.ptr == null && ptr != null) holder.ptr = ptr; holder.count++; } } internal static long remove(IntPtr instance) { long result = 0; Holder holder; if (mObjectMap.TryGetValue(instance, out holder)) { holder.count--; if (holder.count == 0) mObjectMap.Remove(instance); result = holder.count; } return result; } }
ããã§ãªããžã§ã¯ããããŒãžã£ãã§ããŸããã 管ç察象ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã管ç察象å€ç°å¢ã«æž¡ãåã«ãããããããŒãžã£ãŒã«è¿œå ããå¿ èŠããããŸãã ãããã£ãŠãã¯ã©ã¹ABããã³Cã®getUnmanagedã¡ãœãããå€æŽããå¿ èŠããããŸãã ã¯ã©ã¹Cã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
internal IntPtr getUnmanaged() { ObjectManager.add(mHandlerInstance, this); return mHandlerInstance; }
ããã§ãã³ãŒã«ããã¯ãå¿ èŠãªéãæ©èœããããšã確èªã§ããŸãã
ã¢ãžã¥ãŒã«ã®ä»æ§ãèæ ®ããŠãã¯ã©ã¹ãæžãæããClassName_deleteInstanceãžã®ãã¹ãŠã®åŒã³åºããIObject :: releaseãžã®åŒã³åºãã«çœ®ãæããå¿ èŠã«å¿ããŠIObject :: addRefãå®è¡ããããšãå¿ããªãã§ãã ããã ç¹ã«ãããã¯ãã¬ããŒãžã³ã¬ã¯ã¿ãŒããããŒãžã©ãããŒãåé€ããå Žåã§ããModuleExceptionã®ææå°æ©ãªåé€ãåé¿ããã®ã«åœ¹ç«ã¡ãŸãã
ãããã«
å®éãã¢ãžã¥ãŒã«ãçµ±åããŠããéãç§ãã¡ã¯èšå€§ãªææ ãçµéšããå€ãã®ãããã€ãªèšèãåŠã³ãç«ã£ããŸãŸç ãããšãåŠã³ãŸããã ããããããã®èšäºã誰ãã«åœ¹ç«ã€ãã®ã«ãããã®ã§ãããç¥ã¯çŠããããŠããŸãã ãã¡ãããã¡ã¢ãªç®¡çãç¶æ¿ãããã³äŸå€ãæž¡ãåé¡ã解決ããã®ã¯æ¥œããã£ãã§ãã ãããã3ã€ã®ã¯ã©ã¹ããã¯ã»ã©é ãçµ±åãã1ã€ã®ã¡ãœããããã¯çšé ããã®ã§ããã èä¹ ãã¹ãã§ããã
ããã§ããã®ãããªåé¡ãçºçããå Žåã¯ãSublime Textãæ£èŠè¡šçŸãã¹ããããã倧奜ãã§ãã ãã®å°ããªã»ããã¯ã¢ã«ã³ãŒã«äŸåçããç§ãã¡ãæããŸããã
PSã©ã€ãã©ãªçµ±åã®å®äŸã¯ã github.com / simbirsoft-public / pinvoke_exampleã§å ¥æã§ããŸãã