110,537
社区成员
发帖
与我相关
我的任务
分享
class CVTable : IDisposable
{
IntPtr _vtable;
public CVTable(params Delegate[] methods)
{
_vtable = Marshal.AllocHGlobal(methods.Length * Marshal.SizeOf(typeof(IntPtr)));
for (int i = 0; i < methods.Length; ++i)
{
Marshal.WriteIntPtr(_vtable, i * Marshal.SizeOf(typeof(IntPtr)), Marshal.GetFunctionPointerForDelegate(methods[i]));
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (_vtable != IntPtr.Zero)
{
Marshal.FreeHGlobal(_vtable);
_vtable = IntPtr.Zero;
}
disposed = true;
}
}
~CVTable()
{
Dispose(false);
}
public IntPtr CreateVTable(IntPtr @this)
{
IntPtr old = Marshal.ReadIntPtr(@this, 0 * Marshal.SizeOf(typeof(IntPtr)));
Marshal.WriteIntPtr(@this, 0 * Marshal.SizeOf(typeof(IntPtr)), _vtable);
return old;
}
public void ReleaseVTable(IntPtr @this, IntPtr vtable)
{
Marshal.WriteIntPtr(@this, 0 * Marshal.SizeOf(typeof(IntPtr)), vtable);
}
}
partial class CSForC : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
_Dispose();
disposed = true;
}
}
~CSForC()
{
Dispose(false);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct _CForCS
{
public IntPtr _vtable;
public int _nValue;
}
partial class CSForC
{
private IntPtr _basecpp;
private const string dllname = "..\\..\\..\\Debug\\CForCS.dll";
[DllImport(dllname, EntryPoint = "??0CCForCS@@QAE@XZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Constructor([In] IntPtr @this);
[DllImport(dllname, EntryPoint = "??0CCForCS@@QAE@H@Z", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Constructor([In] IntPtr @this, [In, MarshalAs(UnmanagedType.I4)] int value);
[DllImport(dllname, EntryPoint = "??1CCForCS@@QAE@XZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Destructor([In] IntPtr @this);
[DllImport(dllname, EntryPoint = "?Print@CCForCS@@QAEXPB_W@Z", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Print([In] IntPtr @this, [In, MarshalAs(UnmanagedType.LPWStr)]string message);
[DllImport(dllname, EntryPoint = "?GetValue@CCForCS@@QAEHXZ", CallingConvention = CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I4)]
private static extern int _GetValue([In] IntPtr @this);
public CSForC()
{
_basecpp = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(_CForCS)));
_Constructor(_basecpp);
CreateVtable();
}
public CSForC(int value)
{
_basecpp = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(_CForCS)));
_Constructor(_basecpp, value);
CreateVtable();
}
private void _Dispose()
{
if (_basecpp != IntPtr.Zero)
{
ReleaseVtable();
_Destructor(_basecpp);
Marshal.FreeCoTaskMem(_basecpp);
_basecpp = IntPtr.Zero;
}
}
public void Print(string message)
{
_Print(_basecpp, message);
}
public int GetValue()
{
return _GetValue(_basecpp);
}
IntPtr _basecppvtable;
CVTable vtable;
private void CreateVtable()
{
vtable = new CVTable(new _VFunctionBeforeHandler(VFunctionBefore), new _VFunctionAfterHandler(VFunctionAfter));
_basecppvtable = vtable.CreateVTable(_basecpp);
}
private void ReleaseVtable()
{
if (_basecppvtable != IntPtr.Zero)
{
vtable.ReleaseVTable(_basecpp, _basecppvtable);
((IDisposable)vtable).Dispose();
}
}
[DllImport(dllname, EntryPoint = "?VFunctionBefore@CCForCS@@MAEHPB_WPAH@Z", CallingConvention = CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I4)]
private static extern int _VFunctionBefore([In] IntPtr @this, [In, MarshalAs(UnmanagedType.LPWStr)]string message, [Out, MarshalAs(UnmanagedType.I4)] out int value);
[DllImport(dllname, EntryPoint = "?VFunctionAfter@CCForCS@@MAEXPB_WH@Z", CallingConvention = CallingConvention.ThisCall)]
private static extern void _VFunctionAfter([In] IntPtr @this, [In, MarshalAs(UnmanagedType.LPWStr)]string message, [In, MarshalAs(UnmanagedType.I4)]int value);
private delegate int _VFunctionBeforeHandler([In, MarshalAs(UnmanagedType.LPWStr)]string message, [Out, MarshalAs(UnmanagedType.I4)]out int value);
private delegate void _VFunctionAfterHandler([In, MarshalAs(UnmanagedType.LPWStr)]string message, [In, MarshalAs(UnmanagedType.I4)]int value);
protected virtual int VFunctionBefore(string message, out int value)
{
int n = _VFunctionBefore(_basecpp, message, out value);
value = 100;
return n;
}
protected virtual void VFunctionAfter(string message, int value)
{
System.Diagnostics.Debug.WriteLine(string.Format("{0}, {1}.", message, value));
}
}
class Program
{
static void Main(string[] args)
{
var v = new CSForC(123456789);
v.Print("CSMessage ");
System.Diagnostics.Debug.WriteLine(string.Format("GetValue() = {0}", v.GetValue()));
((IDisposable)v).Dispose();
}
}
class CFORCS_API CCForCS
{
public:
CCForCS(void);
CCForCS(int nValue);
~CCForCS(void);
public:
void Print(LPCWSTR pszMessage);
int GetValue(void);
protected:
virtual int VFunctionBefore(LPCWSTR pszMessage, int *pnValue);
virtual void VFunctionAfter(LPCWSTR pszMessage, int nValue);
private:
int _nValue;
};
class CNative
{
public:
int NativeFunction(int a) {}
}
C++/CLI
public ref class CNativeWrapper
{
private:
CNative *m_pNative;
public:
CNativeWrapper() { m_pNative = new CNative; }
int ManagedMethod(int a) { return m_pNative->NativeFunction(a); }
~CNativeWrapper() { delete m_pNative; }
protected:
!CNativeWrapper() { delete m_pNative; }
}
C#
class Program
{
int Main()
{
var nativeWrapper = new CNativeWrapper();
nativeWrapper.ManagedMethod();
return 0;
}
}