网上大部分都是C#调用C++的接口,很少有C++调用C#的,更少有在C++中定义接口类,在C#中实现。
千辛万苦,终于找到一个网址:http://www.tuicool.com/articles/AFjY7j
简单翻译一下,
class __declspec(dllexport) CSimpleClass { public: int value; CSimpleClass(int value) : value(value) { } ~CSimpleClass() { printf("~CSimpleClass\n"); } void M1() { printf("C++/CSimpleClass::M1()\n"); V0(); V1(value); V2(); } virtual void V0() { printf("C++/CSimpleClass::V0()\n"); } virtual void V1(int x) { printf("C++/CSimpleClass::V1(%d)\n", x); } virtual void V2() { printf("C++/CSimpleClass::V2()\n", value); } };
然后用dumpbin.exe等工具查看符号表,也可以直接用文本文件打开,搜关键字CSimpleClass,找到函数的符号(如果不明白,要进修一下C++编译方面的知识):
??0CSimpleClass@@QAE@ABV0@@Z
??0CSimpleClass@@QAE@H@Z
??1CSimpleClass@@QAE@XZ
??4CSimpleClass@@QAEAAV0@ABV0@@Z
??_7CSimpleClass@@6B@
?M1@CSimpleClass@@QAEXXZ
?V0@CSimpleClass@@UAEXXZ
?V1@CSimpleClass@@UAEXH@Z
?V2@CSimpleClass@@UAEXXZ
具体是对应的函数是:
public: __thiscall
CSimpleClass::CSimpleClass(int)
public:
__thiscall CSimpleClass::~CSimpleClass(void)
public: class CSimpleClass & __thiscall
CSimpleClass::operator=(class CSimpleClass const
&)
const
CSimpleClass::`vftable‘
public: void
__thiscall CSimpleClass::M1(void)
public: virtual void __thiscall
CSimpleClass::V0(void)
public: virtual
void __thiscall CSimpleClass::V1(int)
public: virtual void __thiscall
CSimpleClass::V2(void)
接下来是在C#中,定义:
[StructLayout(LayoutKind.Sequential, Pack = 4)] public unsafe struct __CSimpleClass { public IntPtr* _vtable; public int value; }
public unsafe class CSimpleClass : IDisposable { private __CSimpleClass* _cpp; private IntPtr* _oldvtbl; private void InitVtable(__CSimpleClass* ths, IntPtr[] arr, int len) { IntPtr* newvtable = (IntPtr*)Memory.Alloc(len * sizeof(IntPtr)); for (int i = 0; i < len; i++) newvtable[i] = arr[i]; _oldvtbl = ths->_vtable; ths->_vtable = newvtable; } private void ResetVtable(__CSimpleClass* ths) { IntPtr* oldvtbl = ths->_vtable; ths->_vtable = _oldvtbl; Memory.Free(oldvtbl); } // CSimpleClass constructor and destructor [DllImport("cppexp.dll", EntryPoint = "??0CSimpleClass@@QAE@H@Z", CallingConvention = CallingConvention.ThisCall)] private static extern int _CSimpleClass_Constructor(__CSimpleClass* ths, int value); [DllImport("cppexp.dll", EntryPoint = "??1CSimpleClass@@QAE@XZ", CallingConvention = CallingConvention.ThisCall)] private static extern int _CSimpleClass_Destructor(__CSimpleClass* ths); // void M1(); // virtual void V0(); // virtual void V1(int x); // virtual void V2(); [DllImport("cppexp.dll", EntryPoint = "?M1@CSimpleClass@@QAEXXZ", CallingConvention = CallingConvention.ThisCall)] private static extern void _M1(__CSimpleClass* ths); [DllImport("cppexp.dll", EntryPoint = "?V0@CSimpleClass@@UAEXXZ", CallingConvention = CallingConvention.ThisCall)] private static extern void _V0(__CSimpleClass* ths); [DllImport("cppexp.dll", EntryPoint = "?V1@CSimpleClass@@UAEXH@Z", CallingConvention = CallingConvention.ThisCall)] private static extern void _V1(__CSimpleClass* ths, int i); [DllImport("cppexp.dll", EntryPoint = "?V2@CSimpleClass@@UAEXXZ", CallingConvention = CallingConvention.ThisCall)] private static extern void _V2(__CSimpleClass* ths); public delegate void V0_Delegate(); public delegate void V1_Delegate(int i); public delegate void V2_Delegate(); public V0_Delegate _v0_Delegate; public V1_Delegate _v1_Delegate; public V2_Delegate _v2_Delegate; public CSimpleClass(int value) { //Allocate storage for object _cpp = (__CSimpleClass*)Memory.Alloc(sizeof(__CSimpleClass)); //Call constructor _CSimpleClass_Constructor(_cpp, value); //Create delegates for the virtual functions _v0_Delegate = new V0_Delegate(V0); _v1_Delegate = new V1_Delegate(V1); _v2_Delegate = new V2_Delegate(V2); IntPtr[] arr = new IntPtr[3]; arr[0] = Marshal.GetFunctionPointerForDelegate(_v0_Delegate); arr[1] = Marshal.GetFunctionPointerForDelegate(_v1_Delegate); arr[2] = Marshal.GetFunctionPointerForDelegate(_v2_Delegate); //Create a new vtable and replace it in the object InitVtable(_cpp, arr, 3); } public void Dispose() { //reset old vtable pointer ResetVtable(_cpp); //call destructor _CSimpleClass_Destructor(_cpp); //release memory Memory.Free(_cpp); _cpp = null; } public void M1() { _M1(_cpp); } public virtual void V0() { _V0(_cpp); } public virtual void V1(int i) { _V1(_cpp, i); } public virtual void V2() { _V2(_cpp); } }
class CSimpleClassEx : CSimpleClass { public CSimpleClassEx(int value) : base(value) { } public override void V2() { Console.WriteLine("C#/CSimpleClassEx.V2()"); } }
这样就可以试验一下了。如果是在C++中回调C#的集成类,实际上对应的C++中CSimpleClass对象的是:private __CSimpleClass* _cpp;