C#调用C++写的dll,包含结构体转换和C#动态调用dll
2008年08月19日 星期二 17:13
这段时间用C++给客户做了一个通讯的dll。但客户是用C#的,所以研究了下C#,把C++的头文件,改写成C#的。主要是转换了结构体的定义,dll函数的调用,C#中的dll的动态调用,C++和C#之间的时间变量的传递。现在和大家分享一下。 C++的头文件: #pragma once // //设置 // typedef struct _RMusterSettings { DWORD dwDataSize; RComm Comm; RCoData CoData; double RealClock; WORD MeterCount; WORD RecNoMax; struct _RAutoReadSettings { BYTE Enable; BYTE Days[31]; struct _RARTime { BYTE Enable; BYTE Hour; BYTE Min; BYTE Sec; }Time[24]; } RAutoReadSettings; } RMusterSettings; // //通讯类定义 // typedef HANDLE (*CREATEXXXXCOMM)(); typedef INT (*FREEXXXXCOMM)(HANDLE); typedef INT (*XXXXCOMM)(HANDLE,WORD,void *); typedef INT (*XXXXABORT)(HANDLE); class CXXXXComm { private: HINSTANCE hLib; HANDLE hXXXXComm; CREATEXXXXCOMM fnCreateXXXXComm; FREEXXXXCOMM fnFreeXXXXComm; XXXXCOMM fnXXXXComm; XXXXABORT fnXXXXAbort; public: CXXXXComm(PCHAR fileName) { hLib = LoadLibrary(fileName); if (hLib != NULL) { fnCreateXXXXComm = (CREATEXXXXCOMM) GetProcAddress(hLib, "CreateXXXXComm"); fnFreeXXXXComm = (FREEXXXXCOMM) GetProcAddress(hLib, "FreeXXXXComm"); fnXXXXComm = (XXXXCOMM) GetProcAddress(hLib, "XXXXComm"); fnXXXXAbort = (XXXXABORT) GetProcAddress(hLib, "XXXXAbort"); hXXXXComm = fnCreateXXXXComm(); } }; ~CXXXXComm() { if (hLib != NULL) { fnFreeXXXXComm(hXXXXComm); FreeLibrary(hLib); } }; INT Comm(WORD cmd, void * data) { if (hLib != NULL) return fnXXXXComm(hXXXXComm,cmd,data); else return EC_DLL_NOT_FOUND; }; INT Abort() { if (hLib != NULL) return fnXXXXAbort(hXXXXComm); else return 0; }; }; C#的类文件 using System; using System.Runtime.InteropServices; namespace Flagele.rd.CXXXXComm { // //设置 // [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct RARTime { public byte Enable; public byte Hour; public byte Min; public byte Sec; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct RAutoReadSettings { public byte Enable; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public byte[] Days; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public RARTime[] Time; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class RMusterSettings { public uint dwDataSize; public RComm Comm; public RCoData CoData; // public long RealClock; public ushort MeterCount; public ushort RecNoMax; public RAutoReadSettings ARSettings; } // //通讯类 // public class CXXXXComm { private uint hLib; private uint hXXXXComm; private delegate uint CREATEXXXXCOMM(); private delegate uint FREEXXXXCOMM(uint hFe); private delegate uint XXXXCOMM(uint hFe, ushort cmd, [In,Out,MarshalAs(UnmanagedType.AsAny)] Object data); private delegate uint XXXXABORT(uint hFe); private CREATEXXXXCOMM fnCreateXXXXComm; private FREEXXXXCOMM fnFreeXXXXComm; private XXXXCOMM fnXXXXComm; private XXXXABORT fnXXXXAbort; [DllImport("Kernel32")] private static extern uint GetProcAddress(uint handle, String funcname); [DllImport("Kernel32")] private static extern uint LoadLibrary(String funcname); [DllImport("Kernel32")] private static extern uint FreeLibrary(uint handle); private static Delegate GetAddress(uint dllModule, string functionname, Type t) { uint addr = GetProcAddress(dllModule, functionname); if (addr == 0) return null; else return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t); } public CXXXXComm() { hLib = LoadLibrary("XXXXComm.dll"); if (hLib != 0) { fnCreateXXXXComm = (CREATEXXXXCOMM)GetAddress(hLib, "CreateXXXXComm", typeof(CREATEXXXXCOMM)); fnFreeXXXXComm = (FREEXXXXCOMM)GetAddress(hLib, "FreeXXXXComm", typeof(FREEXXXXCOMM)); fnXXXXComm = (XXXXCOMM)GetAddress(hLib, "XXXXComm", typeof(XXXXCOMM)); fnXXXXAbort = (XXXXABORT)GetAddress(hLib, "XXXXAbort", typeof(XXXXABORT)); if (fnCreateXXXXComm != null) { hXXXXComm = fnCreateXXXXComm(); } } } ~CXXXXComm() { if (fnFreeXXXXComm != null) { fnFreeXXXXComm(hXXXXComm); } if (hLib != 0) { FreeLibrary(hLib); } } public uint comm(ushort cmd, [MarshalAs(UnmanagedType.AsAny)] Object data) { if (hLib != 0) { return fnXXXXComm(hXXXXComm, cmd, data); } else return CFeError.EC_DLL_NOT_FOUND; } public uint abort() { if (hLib != 0) { return fnXXXXAbort(hXXXXComm); } else return 0; } } } C#的调用例子 //事先要创建XXXXComm //private CXXXXComm XXXXComm; //public Form1() //{ // InitializeComponent(); // XXXXComm= new CXXXXComm(); //} // //▼写设置 // mustersettings.ARSettings.Enable = 1; for (i = 0; i < 31; i++) mustersettings.ARSettings.Days[i] = 1; for (i = 0; i < 24; i++) { mustersettings.ARSettings.Time[i].Enable = 0; mustersettings.ARSettings.Time[i].Hour = (byte)i; mustersettings.ARSettings.Time[i].Min = 0; mustersettings.ARSettings.Time[i].Sec = 0; } Rec = XXXXComm.comm(CFeCmd.W_MusterAutoRead,(Object)mustersettings); if (Rec == 0) { //成功 }
文献来源:http://hi.baidu.com/flagwes/blog/item/e56aad106cb46607203f2e73.html
|