你的 C++ 函数签名是 Plat_GetAllRegion。 你的代码里可有调用这个??我没有看到在哪一行。还有,就是 C++ 的样例代码,要写完成。 因为 C# 转换就是看 C++ 是如何调用的。 不同的调用方式,在 C# 里面有很多种写法。 所以参数的定义,返回参数的使用。
不好意思,C++ 里面的的方法是这个int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraID; //监控点ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iRegionID; //所属区域ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iControlCell; //所属中心ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceID; //设备ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceChannel; //通道号 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public Int16[] szCameraName; //监控点名称 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraState; //监控点状态 }调用的时候出现了这个错误: 无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。
C++的结构体://监控点信息结构体 typedef struct _tagCameraInfo { int iCameraID; //监控点ID int iRegionID; //所属区域ID int iControlCell; //所属中心ID int iDeviceID; //设备ID int iDeviceChannel; //通道号 char szCameraName[128]; //监控点名称 int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像 //iStoreType[0] //代表是否有设备录像; //iStoreType[1] //代表是否有PCNVR录像; //iStoreType[2] //代表是否有NVR录像; //iStoreType[3] //代表是都有CVR录像。 int iCameraState; //监控点状态 }PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;C++的方法原型:int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);C++的调用示例获取监控点资源(第一次调用获取资源数量,第二次调用获取详细信息)//获取监控点 if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam)) { iErrNum = Plat_GetLastError(); } NeedReadCam = PlatRtnCam; pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam]; if (NULL == pCameraInfo) break; memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO)); if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam)) { iErrNum = Plat_GetLastError(); } C#的结构体定义: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraID; //监控点ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iRegionID; //所属区域ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iControlCell; //所属中心ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceID; //设备ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceChannel; //通道号 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public Int16[] szCameraName; //监控点名称 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraState; //监控点状态 }C#的声明: [DllImport("PlatformSDK.dll", CharSet = CharSet.Ansi)] public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); C#的调用: if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, pCameraInfo, ref PlatRtnCam)) { } pCameraInfo = new _tagCameraInfo[PlatRtnCam];
int CamCount = PlatRtnCam; if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam)) { }
C++的结构体://监控点信息结构体 typedef struct _tagCameraInfo { int iCameraID; //监控点ID int iRegionID; //所属区域ID int iControlCell; //所属中心ID int iDeviceID; //设备ID int iDeviceChannel; //通道号 char szCameraName[128]; //监控点名称 int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像 //iStoreType[0] //代表是否有设备录像; //iStoreType[1] //代表是否有PCNVR录像; //iStoreType[2] //代表是否有NVR录像; //iStoreType[3] //代表是都有CVR录像。 int iCameraState; //监控点状态 }PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;C++的方法原型:int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);C++的调用示例获取监控点资源(第一次调用获取资源数量,第二次调用获取详细信息)//获取监控点 if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam)) { iErrNum = Plat_GetLastError(); } NeedReadCam = PlatRtnCam; pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam]; if (NULL == pCameraInfo) break; memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO)); if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam)) { iErrNum = Plat_GetLastError(); } C#的结构体定义: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraID; //监控点ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iRegionID; //所属区域ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iControlCell; //所属中心ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceID; //设备ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceChannel; //通道号 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public Int16[] szCameraName; //监控点名称 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraState; //监控点状态 }C#的声明: [DllImport("PlatformSDK.dll", CharSet = CharSet.Ansi)] public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); C#的调用: if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, pCameraInfo, ref PlatRtnCam)) { } pCameraInfo = new _tagCameraInfo[PlatRtnCam];
int CamCount = PlatRtnCam; if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam)) { }
不好意思,C++ 里面的的方法是这个int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraID; //监控点ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iRegionID; //所属区域ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iControlCell; //所属中心ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceID; //设备ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceChannel; //通道号 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public Int16[] szCameraName; //监控点名称 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraState; //监控点状态 }调用的时候出现了这个错误: 无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。 string szCameraName ByValTStr 是把 C 的 字符数组,Marshal 为 string.
不好意思,C++ 里面的的方法是这个int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraID; //监控点ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iRegionID; //所属区域ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iControlCell; //所属中心ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceID; //设备ID [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iDeviceChannel; //通道号 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public Int16[] szCameraName; //监控点名称 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 [MarshalAs(UnmanagedType.U4, SizeConst = 4)] public Int32 iCameraState; //监控点状态 }调用的时候出现了这个错误: 无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。 string szCameraName ByValTStr 是把 C 的 字符数组,Marshal 为 string. 谢谢你的帮忙,能具体按点我这些要怎么修改吗,以前很少弄这方面的,谢谢了。
给你一个样例。 typedef struct _ARRAY { int _nValue; char _strValue[256]; } ARRAY;EXTERN_C BOOL __stdcall GetArray(int nIndex, int nCount, ARRAY *pArray, int *pnCount) { *pnCount = nIndex * 2 + 1; if (nCount < *pnCount) { return FALSE; } for (int i = 0; i < *pnCount; ++i) { pArray[i]._nValue = i; sprintf_s(pArray[i]._strValue, _countof(pArray[i]._strValue), "String Index = %d", i); } return TRUE; } class Program { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] struct Array { [MarshalAs(UnmanagedType.I4)] public int intValue; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string stringValue; } [DllImport("..\\..\\..\\Debug\\CForCS.dll")] [return:MarshalAs( UnmanagedType.Bool)] private static extern bool GetArray(int index, int size, IntPtr array, out int count); [DllImport("..\\..\\..\\Debug\\CForCS.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetArray(int index, int size, [In, Out] Array[] array, out int count); static void Main(string[] args) { for (int i = 0;i < 3; ++i) { int count = 0; GetArray(i, 0, IntPtr.Zero, out count); var array = new Array[count]; GetArray(i, count, array, out count); foreach(var item in array) { System.Diagnostics.Debug.WriteLine(string.Format("index = {0}, intValue = {1}, stringValue = {2}.", i, item.intValue, item.stringValue)); } System.Diagnostics.Debug.WriteLine(""); } } }
首先,你要给Plat_GetAllRegion加上extern "C" _declspec(dllexport)的声明,再次,你两次调用的方法不一样,一次是Plat_GetAllRegion,一次是Plat_GetAllCamera,这里姑且就用Plat_GetAllCamera给你写个例子吧。因为没有看到Plat_GetAllCamera的方法体,所以我就直接返回了一个整型的数值,你按下面的操作来做就可以了 1、在C++里添加一个头文件,这里的命名是plat.h//监控点信息结构体 typedef struct _tagCameraInfo { int iCameraID; //监控点ID int iRegionID; //所属区域ID int iControlCell; //所属中心ID int iDeviceID; //设备ID int iDeviceChannel; //通道号 char szCameraName[128]; //监控点名称 int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像
//iStoreType[0] //代表是否有设备录像; //iStoreType[1] //代表是否有PCNVR录像; //iStoreType[2] //代表是否有NVR录像; //iStoreType[3] //代表是都有CVR录像。 int iCameraState; //监控点状态 }PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;extern "C" _declspec(dllexport) int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum); 2、在cpp代码里引用这个头文件#include "plat.h"int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum) { return iUserHandle + iNeedGetNum; } 3、在C#里引用dll,szCameraName要用byte数组而不int16 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct _tagCameraInfo { public Int32 iCameraID; //监控点ID public Int32 iRegionID; //所属区域ID public Int32 iControlCell; //所属中心ID public Int32 iDeviceID; //设备ID public Int32 iDeviceChannel; //通道号 public Byte[] szCameraName; //监控点名称 public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。 public Int32 iCameraState; //监控点状态 } [DllImport("PlatformSDK.dll", EntryPoint = "Plat_GetAllCamera", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); 4、调用 _tagCameraInfo[] info = new _tagCameraInfo[1] { new _tagCameraInfo(){ iCameraID=1, iRegionID=2, iControlCell=3, iDeviceID=4, iDeviceChannel=5, szCameraName=new Byte[]{6,7,8}, iStoreType=new Int32[]{9,10,11}, iCameraState=12 } }; int output = 0; int n = Plat_GetAllCamera(10, 20, info, ref output); Console.WriteLine(n); 5、调试结果为30,具体的方法以你的C++函数为准
谢谢你的解答 方法原型是这样的: int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum);
谢谢你的解答 方法原型是这样的: int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum); int n = Plat_GetAllCamera(10, 20, info, ref output);这个info参数是不是该为ref的,好像是要传进去赋值的。
纠正一下,因为info是数组,所以参数不用加ref,即便它是结构体public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); //声明
int n = Plat_GetAllCamera(10, 20,info, ref output); //调用另外,我这边测试了,传null值不会影响最后的返回值int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, PLAT_CAMERAINFO* pCameraBuffer, int* pOutputNum) { *pOutputNum= *pOutputNum + 100; return iUserHandle + iNeedGetNum; } int output = 10; int n = Plat_GetAllCamera(10, 20, null, ref output); Console.WriteLine(n); Console.WriteLine(output); //30 //110
我调用的代码: int PlatRtnCam = 0; _tagCameraInfo[] pCameraInfo = null; if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, null, ref PlatRtnCam)) { } pCameraInfo = new _tagCameraInfo[PlatRtnCam]; for (int i = 0; i < pCameraInfo.Length; i++) { pCameraInfo[i].szCameraName = new byte[128]; pCameraInfo[i].iStoreType = new int[4]; } int CamCount = PlatRtnCam; if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam)) { }结果在第二次调用的时候,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
你看看C++的代码是怎么写的,这边测试没有任何异常 int g_iLoginHandle = 100; int PlatRtnCam = 0; _tagCameraInfo[] pCameraInfo = null; if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, null, ref PlatRtnCam)) { } pCameraInfo = new _tagCameraInfo[PlatRtnCam]; for (int i = 0; i < pCameraInfo.Length; i++) { pCameraInfo[i].szCameraName = new byte[128]; pCameraInfo[i].iStoreType = new int[4]; } int CamCount = PlatRtnCam; if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam)) { }
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
NeedReadCam = PlatRtnCam;
pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam];
if (NULL == pCameraInfo)
break;
memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO));
if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
你的代码里可有调用这个??我没有看到在哪一行。还有,就是 C++ 的样例代码,要写完成。
因为 C# 转换就是看 C++ 是如何调用的。
不同的调用方式,在 C# 里面有很多种写法。
所以参数的定义,返回参数的使用。
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraID; //监控点ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iRegionID; //所属区域ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iControlCell; //所属中心ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceID; //设备ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceChannel; //通道号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public Int16[] szCameraName; //监控点名称
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraState; //监控点状态
}调用的时候出现了这个错误:
无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。
typedef struct _tagCameraInfo
{
int iCameraID; //监控点ID
int iRegionID; //所属区域ID
int iControlCell; //所属中心ID
int iDeviceID; //设备ID
int iDeviceChannel; //通道号
char szCameraName[128]; //监控点名称
int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像 //iStoreType[0] //代表是否有设备录像;
//iStoreType[1] //代表是否有PCNVR录像;
//iStoreType[2] //代表是否有NVR录像;
//iStoreType[3] //代表是都有CVR录像。
int iCameraState; //监控点状态
}PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;C++的方法原型:int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);C++的调用示例获取监控点资源(第一次调用获取资源数量,第二次调用获取详细信息)//获取监控点
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
NeedReadCam = PlatRtnCam;
pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam];
if (NULL == pCameraInfo)
break;
memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO));
if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
C#的结构体定义: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraID; //监控点ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iRegionID; //所属区域ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iControlCell; //所属中心ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceID; //设备ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceChannel; //通道号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public Int16[] szCameraName; //监控点名称
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraState; //监控点状态
}C#的声明:
[DllImport("PlatformSDK.dll", CharSet = CharSet.Ansi)]
public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum);
C#的调用: if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, pCameraInfo, ref PlatRtnCam))
{ }
pCameraInfo = new _tagCameraInfo[PlatRtnCam];
int CamCount = PlatRtnCam;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam))
{ }
typedef struct _tagCameraInfo
{
int iCameraID; //监控点ID
int iRegionID; //所属区域ID
int iControlCell; //所属中心ID
int iDeviceID; //设备ID
int iDeviceChannel; //通道号
char szCameraName[128]; //监控点名称
int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像 //iStoreType[0] //代表是否有设备录像;
//iStoreType[1] //代表是否有PCNVR录像;
//iStoreType[2] //代表是否有NVR录像;
//iStoreType[3] //代表是都有CVR录像。
int iCameraState; //监控点状态
}PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;C++的方法原型:int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);C++的调用示例获取监控点资源(第一次调用获取资源数量,第二次调用获取详细信息)//获取监控点
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
NeedReadCam = PlatRtnCam;
pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam];
if (NULL == pCameraInfo)
break;
memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO));
if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
C#的结构体定义: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraID; //监控点ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iRegionID; //所属区域ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iControlCell; //所属中心ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceID; //设备ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceChannel; //通道号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public Int16[] szCameraName; //监控点名称
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraState; //监控点状态
}C#的声明:
[DllImport("PlatformSDK.dll", CharSet = CharSet.Ansi)]
public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum);
C#的调用: if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, pCameraInfo, ref PlatRtnCam))
{ }
pCameraInfo = new _tagCameraInfo[PlatRtnCam];
int CamCount = PlatRtnCam;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam))
{ }
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraID; //监控点ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iRegionID; //所属区域ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iControlCell; //所属中心ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceID; //设备ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceChannel; //通道号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public Int16[] szCameraName; //监控点名称
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraState; //监控点状态
}调用的时候出现了这个错误:
无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。
string szCameraName
ByValTStr 是把 C 的 字符数组,Marshal 为 string.
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);百度看说结构体的字段的长度和c++可能不一样,现在做了修改: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraID; //监控点ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iRegionID; //所属区域ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iControlCell; //所属中心ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceID; //设备ID
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iDeviceChannel; //通道号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public Int16[] szCameraName; //监控点名称
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public Int32 iCameraState; //监控点状态
}调用的时候出现了这个错误:
无法封送处理类型为“WindowsApplication1._tagCameraInfo”的字段“szCameraName”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。
string szCameraName
ByValTStr 是把 C 的 字符数组,Marshal 为 string.
谢谢你的帮忙,能具体按点我这些要怎么修改吗,以前很少弄这方面的,谢谢了。
typedef struct _ARRAY
{
int _nValue;
char _strValue[256];
} ARRAY;EXTERN_C BOOL __stdcall GetArray(int nIndex, int nCount, ARRAY *pArray, int *pnCount)
{
*pnCount = nIndex * 2 + 1;
if (nCount < *pnCount)
{
return FALSE;
}
for (int i = 0; i < *pnCount; ++i)
{
pArray[i]._nValue = i;
sprintf_s(pArray[i]._strValue, _countof(pArray[i]._strValue), "String Index = %d", i);
}
return TRUE;
} class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct Array
{
[MarshalAs(UnmanagedType.I4)]
public int intValue;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string stringValue;
}
[DllImport("..\\..\\..\\Debug\\CForCS.dll")]
[return:MarshalAs( UnmanagedType.Bool)]
private static extern bool GetArray(int index, int size, IntPtr array, out int count);
[DllImport("..\\..\\..\\Debug\\CForCS.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetArray(int index, int size, [In, Out] Array[] array, out int count);
static void Main(string[] args)
{
for (int i = 0;i < 3; ++i)
{
int count = 0;
GetArray(i, 0, IntPtr.Zero, out count);
var array = new Array[count];
GetArray(i, count, array, out count);
foreach(var item in array)
{
System.Diagnostics.Debug.WriteLine(string.Format("index = {0}, intValue = {1}, stringValue = {2}.", i, item.intValue, item.stringValue));
}
System.Diagnostics.Debug.WriteLine("");
}
}
}
1、在C++里添加一个头文件,这里的命名是plat.h//监控点信息结构体
typedef struct _tagCameraInfo
{
int iCameraID; //监控点ID
int iRegionID; //所属区域ID
int iControlCell; //所属中心ID
int iDeviceID; //设备ID
int iDeviceChannel; //通道号
char szCameraName[128]; //监控点名称
int iStoreType[4]; //监控点录像位置数组 0代表无录像,1代表有录像
//iStoreType[0] //代表是否有设备录像;
//iStoreType[1] //代表是否有PCNVR录像;
//iStoreType[2] //代表是否有NVR录像;
//iStoreType[3] //代表是都有CVR录像。
int iCameraState; //监控点状态
}PLAT_CAMERAINFO,*LPPLAT_CAMERAINFO;extern "C" _declspec(dllexport) int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);
2、在cpp代码里引用这个头文件#include "plat.h"int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum)
{
return iUserHandle + iNeedGetNum;
}
3、在C#里引用dll,szCameraName要用byte数组而不int16 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagCameraInfo
{
public Int32 iCameraID; //监控点ID
public Int32 iRegionID; //所属区域ID
public Int32 iControlCell; //所属中心ID
public Int32 iDeviceID; //设备ID
public Int32 iDeviceChannel; //通道号
public Byte[] szCameraName; //监控点名称
public Int32[] iStoreType; ////监控点录像位置数组 0代表无录像,1代表有录像;iStoreType[0]代表是否有设备录像;iStoreType[1]代表是否有PCNVR录像;iStoreType[2]代表是否有NVR录像;iStoreType[3]代表是都有CVR录像。
public Int32 iCameraState; //监控点状态
} [DllImport("PlatformSDK.dll", EntryPoint = "Plat_GetAllCamera", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, _tagCameraInfo[] pCameraBuffer, ref int pOutputNum);
4、调用 _tagCameraInfo[] info = new _tagCameraInfo[1] {
new _tagCameraInfo(){
iCameraID=1,
iRegionID=2,
iControlCell=3,
iDeviceID=4,
iDeviceChannel=5,
szCameraName=new Byte[]{6,7,8},
iStoreType=new Int32[]{9,10,11},
iCameraState=12
} };
int output = 0;
int n = Plat_GetAllCamera(10, 20, info, ref output);
Console.WriteLine(n);
5、调试结果为30,具体的方法以你的C++函数为准
方法原型是这样的:
int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);
方法原型是这样的:
int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum);
int n = Plat_GetAllCamera(10, 20, info, ref output);这个info参数是不是该为ref的,好像是要传进去赋值的。
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
NeedReadCam = PlatRtnCam;
pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam];
if (NULL == pCameraInfo)
break;
memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO));
if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
是的,你就这样写吧public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, ref _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); //声明int n = Plat_GetAllCamera(10, 20,ref info, ref output); //调用
是的,你就这样写吧public unsafe static extern int Plat_GetAllCamera(int iUserHandle, int iNeedGetNum, ref _tagCameraInfo[] pCameraBuffer, ref int pOutputNum); //声明int n = Plat_GetAllCamera(10, 20,ref info, ref output); //调用
感谢你的关注,下面是C++的具体调用,第一次调用第二个参数是C++传了一个NULL,我这边传进去null,最后一个ref的参数就不能正确赋值了。//获取监控点
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0,NULL, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
NeedReadCam = PlatRtnCam;
pCameraInfo = new (std::nothrow) PLAT_CAMERAINFO[NeedReadCam];
if (NULL == pCameraInfo)
break;
memset(pCameraInfo, 0, NeedReadCam * sizeof(PLAT_CAMERAINFO));
if (-1 == Plat_GetAllCamera(g_iLoginHandle, NeedReadCam, pCameraInfo, &PlatRtnCam))
{
iErrNum = Plat_GetLastError();
}
int n = Plat_GetAllCamera(10, 20,info, ref output); //调用另外,我这边测试了,传null值不会影响最后的返回值int Plat_GetAllCamera(int iUserHandle,
int iNeedGetNum,
PLAT_CAMERAINFO* pCameraBuffer,
int* pOutputNum)
{
*pOutputNum= *pOutputNum + 100;
return iUserHandle + iNeedGetNum;
} int output = 10;
int n = Plat_GetAllCamera(10, 20, null, ref output);
Console.WriteLine(n);
Console.WriteLine(output);
//30
//110
_tagCameraInfo[] pCameraInfo = null;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, null, ref PlatRtnCam))
{ }
pCameraInfo = new _tagCameraInfo[PlatRtnCam];
for (int i = 0; i < pCameraInfo.Length; i++)
{
pCameraInfo[i].szCameraName = new byte[128];
pCameraInfo[i].iStoreType = new int[4];
}
int CamCount = PlatRtnCam;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam))
{ }结果在第二次调用的时候,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
你看看C++的代码是怎么写的,这边测试没有任何异常 int g_iLoginHandle = 100;
int PlatRtnCam = 0;
_tagCameraInfo[] pCameraInfo = null;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, 0, null, ref PlatRtnCam))
{ }
pCameraInfo = new _tagCameraInfo[PlatRtnCam];
for (int i = 0; i < pCameraInfo.Length; i++)
{
pCameraInfo[i].szCameraName = new byte[128];
pCameraInfo[i].iStoreType = new int[4];
}
int CamCount = PlatRtnCam;
if (-1 == Plat_GetAllCamera(g_iLoginHandle, CamCount, pCameraInfo, ref PlatRtnCam))
{ }