7,540
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AShura.CSForC
{
class Program
{
static void Main(string[] args)
{
var v = new CSForC(123456789);
v.Print("CSMessage ");
int value = v.GetValue();
System.Diagnostics.Debug.WriteLine(string.Format("GetValue() = {0}", value));
int staticValue = NativeImport.nCForCS;
System.Diagnostics.Debug.WriteLine(string.Format("StaticValue = {0}", staticValue));
NativeImport.nCForCS = 987654321;
staticValue = NativeImport.nCForCS;
System.Diagnostics.Debug.WriteLine(string.Format("StaticValue = {0}", staticValue));
string stringValue = v.GetString(1);
System.Diagnostics.Debug.WriteLine(string.Format("StringValue() = {0}", stringValue));
stringValue = v.GetString(2);
System.Diagnostics.Debug.WriteLine(string.Format("StringValue() = {0}", stringValue));
int memberValue = v.MemberValue;
System.Diagnostics.Debug.WriteLine(string.Format("MemberValue = {0}", memberValue));
v.MemberValue = 111111111;
memberValue = v.MemberValue;
System.Diagnostics.Debug.WriteLine(string.Format("MemberValue = {0}", memberValue));
byte[][] data = v.Data;
for (int i = 0; i < data.Length; ++i)
{
if (data[i] != null)
{
for (int j = 0; j < data[i].Length; ++j)
{
System.Diagnostics.Debug.Write(string.Format("{0}, ", data[i][j]));
}
System.Diagnostics.Debug.WriteLine("");
}
}
((IDisposable)v).Dispose();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace AShura.CSForC
{
static class NativeImport
{
class DllImportedField
{
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary([In] string lpFileName);
[DllImport("Kernel32.dll")]
private static extern void FreeLibrary([In] IntPtr hModule);
[DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress([In] IntPtr hModule, [In] string lpProcName);
private IntPtr hModule;
private IntPtr ptrAddress;
public DllImportedField(string dllname, string fieldname)
{
hModule = LoadLibrary(dllname);
ptrAddress = GetProcAddress(hModule, fieldname);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (hModule != IntPtr.Zero)
{
FreeLibrary(hModule);
}
disposed = true;
}
}
~DllImportedField()
{
Dispose(false);
}
public T GetValue<T>()
{
return (T)Marshal.PtrToStructure(ptrAddress, typeof(T));
}
public void SetValue<T>(T value)
{
Marshal.StructureToPtr(value, ptrAddress, false);
}
}
private static DllImportedField _nCForCS = new DllImportedField("..\\..\\..\\Debug\\CForCS.dll", "?nCForCS@@3HA");
public static int nCForCS
{
get
{
return _nCForCS.GetValue<int>();
}
set
{
_nCForCS.SetValue(value);
}
}
}
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(Object @this, IntPtr ptrThis, int index, int offsetOfThis)
{
IntPtr old = Marshal.ReadIntPtr(ptrThis, index * Marshal.SizeOf(typeof(IntPtr)));
Marshal.WriteIntPtr(ptrThis, index * Marshal.SizeOf(typeof(IntPtr)), _vtable);
Marshal.WriteIntPtr(ptrThis, offsetOfThis, GCHandle.ToIntPtr(GCHandle.Alloc(@this)));
return old;
}
public void ReleaseVTable(IntPtr ptrThis, int index, int offsetOfThis, IntPtr vtable)
{
if (ptrThis != IntPtr.Zero)
{
GCHandle.FromIntPtr(Marshal.ReadIntPtr(ptrThis, offsetOfThis)).Free();
Marshal.WriteIntPtr(ptrThis, index * Marshal.SizeOf(typeof(IntPtr)), vtable);
}
}
public Object GetThisObject(IntPtr ptrThis, int offsetOfThis)
{
return GCHandle.FromIntPtr(Marshal.ReadIntPtr(ptrThis, offsetOfThis)).Target;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct _CForCS
{
private IntPtr _vtable;
public int _MemberValue;
private int _nValue;
}
[StructLayout(LayoutKind.Sequential)]
public struct _READ_DATA
{
public int Length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] Data;
}
[StructLayout(LayoutKind.Sequential)]
public struct _READ_DATA_ARRAY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public _READ_DATA[] Data;
}
public class CForCS : IDisposable
{
private const string dllname = "..\\..\\..\\Debug\\CForCS.dll";
private static int _BaseClassSize = Marshal.SizeOf(typeof(_CForCS));
private IntPtr _basecpp;
private IntPtr _basecppvtable;
private static CVTable _vtable = new CVTable(
new _VFunctionBeforeHandler(_VFunctionBefore_),
new _VFunctionAfterHandler(_VFunctionAfter_)
);
[DllImport(dllname, EntryPoint = "??0CCForCS@@QAE@XZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Constructor([In] IntPtr @this);
public CForCS()
{
_basecpp = Marshal.AllocCoTaskMem(_BaseClassSize + Marshal.SizeOf(typeof(IntPtr)));
_Constructor(_basecpp);
_basecppvtable = _vtable.CreateVTable(this, _basecpp, 0, _BaseClassSize);
}
[DllImport(dllname, EntryPoint = "??0CCForCS@@QAE@H@Z", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Constructor([In] IntPtr @this, [In, MarshalAs(UnmanagedType.I4)] int value);
public CForCS(int value)
{
_basecpp = Marshal.AllocCoTaskMem(_BaseClassSize + Marshal.SizeOf(typeof(IntPtr)));
_Constructor(_basecpp, value);
_vtable.CreateVTable(this, _basecpp, 0, _BaseClassSize);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
[DllImport(dllname, EntryPoint = "??1CCForCS@@QAE@XZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _Destructor([In] IntPtr @this);
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (_basecpp != IntPtr.Zero)
{
_vtable.ReleaseVTable(_basecpp, 0, _BaseClassSize, _basecppvtable);
_Destructor(_basecpp);
Marshal.FreeCoTaskMem(_basecpp);
_basecpp = IntPtr.Zero;
}
disposed = true;
}
}
~CForCS()
{
Dispose(false);
}
[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);
public void Print(string message)
{
_Print(_basecpp, message);
}
[DllImport(dllname, EntryPoint = "?GetValue@CCForCS@@QAEHXZ", CallingConvention = CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I4)]
private static extern int _GetValue([In] IntPtr @this);
public int GetValue()
{
return _GetValue(_basecpp);
}
public int MemberValue
{
get
{
return Marshal.ReadInt32(_basecpp, (int)Marshal.OffsetOf(typeof(_CForCS), "_MemberValue"));
}
set
{
Marshal.WriteInt32(_basecpp, (int)Marshal.OffsetOf(typeof(_CForCS), "_MemberValue"), value);
}
}
[DllImport(dllname, EntryPoint = "?GetBSTR@CCForCS@@QAEPA_WH@Z", CallingConvention = CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string _GetGetBSTR([In] IntPtr @this, [In, MarshalAs(UnmanagedType.I4)] int index);
public string GetString(int index)
{
return _GetGetBSTR(_basecpp, index);
}
[DllImport(dllname, EntryPoint = "?ReadData@CCForCS@@QAEHPAX@Z", CallingConvention = CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool _ReadData([In] IntPtr @this, [In] IntPtr data);
public byte[][] Data
{
get
{
int Size = Marshal.SizeOf(typeof(_READ_DATA));
IntPtr ptrData = Marshal.AllocHGlobal(3 * Size);
if (_ReadData(_basecpp, ptrData))
{
byte[][] d = new byte[3][];
for (int i = 0; i < d.Length; ++i)
{
var data = (_READ_DATA)Marshal.PtrToStructure(ptrData + i * Size, typeof(_READ_DATA));
d[i] = new byte[data.Length];
Array.Copy(data.Data, d[i], d[i].Length);
}
return d;
}
throw new Exception();
}
}
[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);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int _VFunctionBeforeHandler([In] IntPtr @this, [In, MarshalAs(UnmanagedType.LPWStr)]string message, [Out, MarshalAs(UnmanagedType.I4)]out int value);
private static int _VFunctionBefore_([In] IntPtr @this, string message, out int value)
{
return ((CForCS)_vtable.GetThisObject(@this, _BaseClassSize)).VFunctionBefore(message, out value);
}
protected virtual int VFunctionBefore(string message, out int value)
{
return _VFunctionBefore(_basecpp, message, out 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);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void _VFunctionAfterHandler([In] IntPtr @this, [In, MarshalAs(UnmanagedType.LPWStr)]string message, [In, MarshalAs(UnmanagedType.I4)]int value);
private static void _VFunctionAfter_([In] IntPtr @this, string message, int value)
{
((CForCS)_vtable.GetThisObject(@this, _BaseClassSize)).VFunctionAfter(message, value);
}
protected virtual void VFunctionAfter(string message, int value)
{
_VFunctionAfter(_basecpp, message, value);
}
}
class CSForC : CForCS
{
public CSForC()
{
}
public CSForC(int value)
: base(value)
{
}
protected override int VFunctionBefore(string message, out int value)
{
int n = base.VFunctionBefore(message, out value);
value = 100;
return n;
}
protected override void VFunctionAfter(string message, int value)
{
System.Diagnostics.Debug.WriteLine(string.Format("{0}, {1}.", message, value));
}
}
}
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 CFORCS_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// CFORCS_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef CFORCS_EXPORTS
#define CFORCS_API __declspec(dllexport)
#else
#define CFORCS_API __declspec(dllimport)
#endif
struct READ_DATA
{
int nLength;
unsigned char btsData[256];
};
// 此类是从 AShura.CForCS.dll 导出的
class CFORCS_API CCForCS
{
public:
CCForCS(void);
CCForCS(int nValue);
~CCForCS(void);
public:
void Print(LPCWSTR pszMessage);
int GetValue(void);
BSTR GetBSTR(int nIndex);
BOOL ReadData(void *pOut);
int MemberValue;
protected:
virtual int VFunctionBefore(LPCWSTR pszMessage, int *pnValue);
virtual void VFunctionAfter(LPCWSTR pszMessage, int nValue);
private:
int _nValue;
};
extern CFORCS_API int nCForCS;
CFORCS_API int fnCForCS(void);
// CForCS.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "CForCS.h"
// 这是导出变量的一个示例
CFORCS_API int nCForCS=0;
// 这是导出函数的一个示例。
CFORCS_API int fnCForCS(void)
{
AUTOTRACEX;
return 42;
}
// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 AShura.CForCS.h
CCForCS::CCForCS()
: _nValue(0)
, MemberValue(0)
{
AUTOTRACEX;
}
CCForCS::~CCForCS()
{
AUTOTRACEX;
}
CCForCS::CCForCS(int nValue)
: _nValue(nValue)
, MemberValue(nValue)
{
AUTOTRACEX;
}
int CCForCS::GetValue(void)
{
AUTOTRACEX;
return _nValue + MemberValue;
}
BSTR CCForCS::GetBSTR(int nIndex)
{
AUTOTRACEX;
WCHAR szNumber[32];
swprintf_s(szNumber, _countof(szNumber), L"BSTR index = %d.", nIndex);
return SysAllocString(szNumber);
}
BOOL CCForCS::ReadData(void *p)
{
AUTOTRACEX;
READ_DATA rd[3];
for (int i = 0; i < 3; ++i)
{
rd[i].nLength = (i + 1) * 10;
for (int j = 0; j < rd[i].nLength; ++j)
{
rd[i].btsData[j] = j;
}
}
memcpy_s(p, sizeof(rd), &rd, sizeof(rd));
return TRUE;
}
void CCForCS::Print(LPCWSTR pszMessage)
{
AUTOTRACEX;
int nValue = 0x12345;
int n = VFunctionBefore(pszMessage, &nValue);
TR(L"message = %s, value = %d, CForCS = %d.", pszMessage, n, nValue);
VFunctionAfter(pszMessage, nValue);
}
int CCForCS::VFunctionBefore(LPCWSTR pszMessage, int *pnValue)
{
AUTOTRACEX;
TR(L"Before: message = %s, value = %d, CForCS = %d.", pszMessage, _nValue, nCForCS);
if (pnValue)
{
*pnValue = nCForCS;
}
return _nValue;
}
void CCForCS::VFunctionAfter(LPCWSTR pszMessage, int nValue)
{
AUTOTRACEX;
nCForCS = nValue;
TR(L"After: message = %s, value = %d, CForCS = %d.", pszMessage, _nValue, nCForCS);
}