1_C# 实现VMS客户端——调用C++ SDK
2014-09-06 18:44
351 查看
声明:
本博客为原创博客,主要讲述使用C#语言调用服务端SDK方式完成VMS客户端完整功能实现,转载请声明出处。
如有技术问题或需交流可直接联系本人邮箱:chuiwenwei@163.com
简述:
在C/S架构设计下,客户端与服务端进行通信有多种方式可选,常用的就是SDK,最大的有点便是便于厂家间平台对接。本篇将从多个方面详尽描述如何使用C#调用C++ SDK。
目录:
调用Dll
如何调用C++ Dll接口
C++数据类型与C#数据类型对照表
结构体转换
多级嵌套结构体转换
回调函数转换
1.调用Dll
首先确定C++提供的Dll文件,一般厂家或是自己部门服务端部分都会提供详尽的Dll、h、lib文件及接口使用文档。对于C#开发只需使用Dll文件即可。此处我将假设开发者是将Dll文件放置于与可执行文件在同一目录下,比如你的可执行文件在C:\,那么将Dll文件也放置于这个目录下,便于开发调试。
2.如何调用C++ Dll接口
3.C++数据类型与C#数据类型对照表
3.C++结构体类型与C#结构体类型对照表
C++里面结构体定义没有什么可讲的,主要是很多编程人员的编程习惯是直接使用结构体定义一个结构体指针来用,此时会让很多人在转换的时候不知所措,此时主要看接口中的参数是使用的结构体还是结构体指针,那此时对应到C#里面也就是是否加ref的问题。另外有点结构体在转换时C#端还需要加入Pack = 1的声明,否则会出现明显的错位问题,这个可以通过调试明显看到。
4.多级嵌套结构体转换
一般用于返回多组查询结果中。
5.回调函数转换
本博客为原创博客,主要讲述使用C#语言调用服务端SDK方式完成VMS客户端完整功能实现,转载请声明出处。
如有技术问题或需交流可直接联系本人邮箱:chuiwenwei@163.com
简述:
在C/S架构设计下,客户端与服务端进行通信有多种方式可选,常用的就是SDK,最大的有点便是便于厂家间平台对接。本篇将从多个方面详尽描述如何使用C#调用C++ SDK。
目录:
调用Dll
如何调用C++ Dll接口
C++数据类型与C#数据类型对照表
结构体转换
多级嵌套结构体转换
回调函数转换
1.调用Dll
首先确定C++提供的Dll文件,一般厂家或是自己部门服务端部分都会提供详尽的Dll、h、lib文件及接口使用文档。对于C#开发只需使用Dll文件即可。此处我将假设开发者是将Dll文件放置于与可执行文件在同一目录下,比如你的可执行文件在C:\,那么将Dll文件也放置于这个目录下,便于开发调试。
2.如何调用C++ Dll接口
Dll接口定义格式简述: C++ : extern + 返回类型 + _stdcall + 函数名称(参数定义); C# : [Dllmport("接口所在Dll",SetLastError = true)] public static extern +返回类型 + 函数名称(参数定义); 确定Dll中提供的接口部分,举例我使用的服务端提供的Dll名称为:CMS_ClientComm.dll,那么我调用此Dll中一个接口:CMS_Init() C++ :extern int __stdcall CMS_Init(); C#: [DllImport("CMS_ClientComm.dll", SetLastError = true)] public static extern int CMS_Init();
3.C++数据类型与C#数据类型对照表
C++ | c# |
int | int |
unsigned int | uint |
bool | byte |
float | float |
OUT float& | ref float |
OUT int& | ref int |
long* | long[] |
Out char* | ref string |
OUT char * | byte[] |
char* | byte[] |
void* | IntPtr |
__int64 | long |
unsigned short | ushort |
C++里面结构体定义没有什么可讲的,主要是很多编程人员的编程习惯是直接使用结构体定义一个结构体指针来用,此时会让很多人在转换的时候不知所措,此时主要看接口中的参数是使用的结构体还是结构体指针,那此时对应到C#里面也就是是否加ref的问题。另外有点结构体在转换时C#端还需要加入Pack = 1的声明,否则会出现明显的错位问题,这个可以通过调试明显看到。
类型1:正常使用结构体 C++: struct CMS_LOCAL_RECORD_SET { char szFilePath[256]; int iFileType; int iTimeLen; bool bAudio; unsigned int uiReserved[4]; }; extern int __stdcall CMS_StartRecordLiveStreamAsFile(IN CAMERA_HANDLE hCamera,IN CMS_LOCAL_RECORD_SET set); C#: [StructLayout(LayoutKind.Sequential,Pack= 1)] public struct CMS_LOCAL_RECORD_SET { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] szFilePath; public int iFileType; public int iTimeLen; public byte bAudio; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] uiReserve; }; [DllImport("CMS_ClientComm.dll", SetLastError = true)] public static extern int CMS_StartRecordLiveStreamAsFile(IntPtr cameraHandle, CMS_LOCAL_RECORD_SET set);
类型2:(正常转换,只需注意数组转换时使用ByValArray,并注明数组大小。结构体参数其实为指针,对应的C#转换用引用类型) C++: typedef struct CMS_LogonData { char cSvrIP[64]; char cUser[64]; char cPwd[64]; }*LPCMS_LogonData; C#: [StructLayout(LayoutKind.Sequential)] public struct CMS_LogonData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] cSvrIP; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] cUser; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] cPwd; }; 此时接口中的调用: C++: extern void* __stdcall CMS_Logon(IN LPCMS_LogonData pData); C#:(加ref引用标示) [DllImport("CMS_ClientComm.dll", SetLastError = true)] public static extern IntPtr CMS_Logon(ref CMS_LogonData logonData);
类型3:(有时需要加Pack = 1,否则会出现字符错位问题) C++: typedef struct CMS_NAME_FILE_RULE_SET { char szSuffix[10]; char szPrefix[40]; bool bIncludeCameraName; bool bIncludeBeginTime; unsigned int uiReserved[2]; }*PCMS_NAME_FILE_RULE_SET; C# [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CMS_NAME_FILE_RULE_SET { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] szSuffix; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] szPrefix; public byte bIncludeCameraName; public byte bIncludeBeginTime; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] uiReserved; }
4.多级嵌套结构体转换
一般用于返回多组查询结果中。
C++: struct CMS_DATE { unsigned short wYear; unsigned short wMonth; unsigned short wDay; }; struct CMS_TIME { unsigned short wHour; unsigned short wMinute; unsigned short wSecond; }; typedef struct CMS_DeviceRecordPlan { void * hRecord; char cType; CMS_TIME cmsStartTime; CMS_TIME cmsEndTime; CMS_DATE cmsDate; int nWeek[7]; char cName[48]; int nSyncAudio; }*LPCMS_DeviceRecordPlan; typedef struct CMS_RecordPlanRes { int unPlanNum; CMS_DeviceRecordPlan sRecordPlan[1024]; }*LPCMS_RecordPlanRes; extern int __stdcall CMS_GetRecordPlan(IN void* hCamera,OUT LPCMS_RecordPlanRes *pData); C#: [StructLayout(LayoutKind.Sequential)] public struct CMS_TIME { public ushort wHour; public ushort wMinute; public ushort wSecond; }; [StructLayout(LayoutKind.Sequential)] public struct CMS_DATE { public ushort wYear; public ushort wMonth; public ushort wDay; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CMS_DeviceRecordPlan { public IntPtr hRecord; public byte cType; public CMS_TIME cmsStartTime; public CMS_TIME cmsEndTime; public CMS_DATE cmsDate; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public int[] nWeek; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] cName; public int nSyncAudio; }; [StructLayout(LayoutKind.Sequential,Pack = 1)] public struct CMS_RecordPlanRes { public int unPlanNum; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public CMS_DeviceRecordPlan[] sRecordPlan; }; [DllImport("CMS_ClientComm.dll", SetLastError = true)] public static extern int CMS_GetRecordPlan(IntPtr cameraHandle, ref CMS_RecordPlanRes[] recordPlans);
5.回调函数转换
C++: typedef struct CMS_MessageEx { void* hSer; int nEventType; char cDesc[260]; void* pContext; long* pReserve; long* pReserve1; }*LPCMS_MessageEx; typedef void (__stdcall *pfnRecvMsgEx)(LPCMS_MessageEx pLog); extern int __stdcall CMS_SetCB_RecvMsgEx(IN SERVER_HANDLE hLID,IN pfnRecvMsgEx pLogFuncEx,IN void* pContext); C#: [StructLayout(LayoutKind.Sequential)] public struct CMS_MessageEx { public IntPtr hSer; public int nEventType; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)] public byte[] cDesc; public IntPtr pContext; public IntPtr pReserve; public IntPtr pReserve1; }; public delegate void CallBackRecvMsgEx(ref CMS_MessageEx pLog); [DllImport("CMS_ClientComm.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)] public static extern int CMS_SetCB_RecvMsgEx(IntPtr serverHandle, CallBackRecvMsgEx pLogFunc, IntPtr pContext);
相关文章推荐
- gsoap实现C#(wpf)客户端调用C++服务器端
- C++调用DotNet类库实现ISAPI Filter(C#)
- java中使用C++指针实现java调用C#
- 2_C# 实现VMS客户端——使用DotNetBar 10.9.0.4控件库
- 10_C# 实现VMS客户端——控件_ButtonX
- 6_C# 实现VMS客户端——代码架构设计
- 使用IDispatch::Invoke函数在C++中调用C#实现的托管类库方法
- C++调用C#生成的DLL实现及注意事项
- 3_C# 实现VMS客户端——使用log4net 写日志
- C#实现调用C/C++中的函数
- 9_C# 实现VMS客户端——控件_TextBoxX
- c# 调用c++带有回调函数方法的实现
- C# 实现 客户端 对实时数据的采集 上传至服务端;在服务端把保存到内存中;供WEB页面调用
- 4_C# 实现VMS客户端——窗体架构设计
- 使用IDispatch::Invoke函数在C++中调用C#实现的托管类库方法
- 会话WCF服务 -> C# WCF COM 客户端 双工通信 -> C++通过COM调用C# WCF客户端
- 8_C# 实现VMS客户端——窗体设计_自定义标题窗体
- C# 调用C++写的dll的实现方法
- 7_C# 实现VMS客户端——窗体设计_无标题窗体设计
- 5_C# 实现VMS客户端——软件架构设计