C#调用C++写的dll问题

nvshenxp 2012-04-05 10:56:41
有个C++写的视频服务器的SDK,需要在C#下调用,但是改来改去总是有问题,无法正确采集图像,请大虾们指点一二,谢谢!类型转换上面不知道是不是有问题,但是如果一开始调用初始化函数的时候就会报“尝试读取或写入受保护的内存...”,如果不调用初始化函数,则不报错,但是图像仍然不显示。
需要调用的C++代码

/// 设备信息
typedef struct _H264_DVR_DEVICEINFO
{
char sSoftWareVersion[64]; ///< 软件版本信息
char sHardWareVersion[64]; ///< 硬件版本信息
char sEncryptVersion[64]; ///< 加密版本信息
SDK_SYSTEM_TIME tmBuildTime;///< 软件创建时间
char sSerialNumber[64]; ///< 设备序列号
int byChanNum; ///< 视频输入通道数
int iVideoOutChannel; ///< 视频输出通道数
int byAlarmInPortNum; ///< 报警输入通道数
int byAlarmOutPortNum; ///< 报警输出通道数
int iTalkInChannel; ///< 对讲输入通道数
int iTalkOutChannel; ///< 对讲输出通道数
int iExtraChannel; ///< 扩展通道数
int iAudioInChannel; ///< 音频输入通道数
int iCombineSwitch; ///< 组合编码通道分割模式是否支持切换
int iDigChannel; ///<数字通道数
unsigned int uiDeviceRunTime; ///<系统运行时间
}H264_DVR_DEVICEINFO,*LPH264_DVR_DEVICEINFO;

typedef struct H264_DVR_CLIENTINFO{
int nChannel; //通道号
int nStream; //0表示主码流,为1表示子码流
int nMode; //0:TCP方式,1:UDP方式,2:多播方式,3 - RTP方式,4-音视频分开(TCP)
int nComType; //只对组合编码通道有效, 组合编码通道的拼图模式
void* hWnd;
H264_DVR_CLIENTINFO()
{
hWnd=0;
}


}*LPH264_DVR_CLIENTINFO;

//服务器断开回调原形
typedef void (CALL_METHOD *fDisConnect)(long lLoginID, char *pchDVRIP, long nDVRPort, unsigned long dwUser);
//*** */SDK初始化
H264_DVR_API long CALL_METHOD H264_DVR_Init(fDisConnect cbDisConnect, unsigned long dwUser);

//打开实时预览
H264_DVR_API long CALL_METHOD H264_DVR_RealPlay(long lLoginID, LPH264_DVR_CLIENTINFO lpClientInfo);

我调用时候的代码


/// <summary>
/// 设备信息
/// H264_DVR_DEVICEINFO,*LPH264_DVR_DEVICEINFO;
/// </summary>
public struct H264_DVR_DEVICEINFO
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] sSoftWareVersion; ///< 软件版本信息
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] sHardWareVersion; ///< 硬件版本信息
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] sEncryptVersion; ///< 加密版本信息
public SDK_SYSTEM_TIME tmBuildTime;///< 软件创建时间
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] sSerialNumber; ///< 设备序列号
public Int32 byChanNum; ///< 视频输入通道数
public Int32 iVideoOutChannel; ///< 视频输出通道数
public Int32 byAlarmInPortNum; ///< 报警输入通道数
public Int32 byAlarmOutPortNum; ///< 报警输出通道数
public Int32 iTalkInChannel; ///< 对讲输入通道数
public Int32 iTalkOutChannel; ///< 对讲输出通道数
public Int32 iExtraChannel; ///< 扩展通道数
public Int32 iAudioInChannel; ///< 音频输入通道数
public Int32 iCombineSwitch; ///< 组合编码通道分割模式是否支持切换
public Int32 iDigChannel; ///<数字通道数
public Int32 uiDeviceRunTime; ///<系统运行时间
}

/// <summary>
/// *LPH264_DVR_CLIENTINFO;
/// </summary>
public struct H264_DVR_CLIENTINFO
{
/// <summary>
/// //通道号
/// </summary>
public int nChannel;
/// <summary>
/// //0表示主码流,为1表示子码流
/// </summary>
public int nStream;
/// <summary>
/// //0:TCP方式,1:UDP方式,2:多播方式,3 - RTP方式,4-音视频分开(TCP)
/// </summary>
public int nMode;
/// <summary>
/// //只对组合编码通道有效, 组合编码通道的拼图模式
/// </summary>
public int nComType;
public IntPtr hWnd;
//H264_DVR_CLIENTINFO(IntPtr hWnd)
//{
// hWnd = IntPtr.Zero;
//}
}
/// <summary>
/////服务器断开回调原形
/// typedef void (CALL_METHOD *fDisConnect)(long lLoginID, char *pchDVRIP, long nDVRPort, unsigned long dwUser);
/// </summary>
public delegate void fDisConnect(int lLoginID, string pchDVRIP, int nDVRPort, uint dwUser);
/// <summary>
/////*** */SDK初始化
/// H264_DVR_API long CALL_METHOD H264_DVR_Init(fDisConnect cbDisConnect, unsigned long dwUser);
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_Init(fDisConnect cbDisConnect, uint dwUser);
/// <summary>
/////获取错误信息
/// H264_DVR_API long CALL_METHOD H264_DVR_GetLastError();
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_GetLastError();
/// <summary>
///向设备注册
///H264_DVR_API long CALL_METHOD H264_DVR_Login(char *sDVRIP, unsigned short wDVRPort, char *sUserName, char *sPassword,LPH264_DVR_DEVICEINFO lpDeviceInfo, int *error);
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_Login(string sDVRIP, ushort wDVRPort, string sUserName, string sPassword, ref H264_DVR_DEVICEINFO lpDeviceInfo, IntPtr error);
/// <summary>
///打开实时预览
///H264_DVR_API long CALL_METHOD H264_DVR_RealPlay(long lLoginID, LPH264_DVR_CLIENTINFO lpClientInfo);
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_RealPlay(int lLoginID, ref H264_DVR_CLIENTINFO lpClientInfo);

...全文
420 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjhnet 2013-05-31
  • 打赏
  • 举报
回复
您好,我现在也在做和你这个一样工厂的远程监控,想在你这互相探讨一下。希望您能给我这个机会, 谢谢 QQ779242794
mingcsharp 2012-04-06
  • 打赏
  • 举报
回复
把结构换成类试一试,
nvshenxp 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
DVR32位的我在用,你这个是64位sdk的dvs的没用过
[/Quote]
那请问下,我调用初始化的时候是不是参数有问题?
zincy 2012-04-06
  • 打赏
  • 举报
回复
DVR32位的我在用,你这个是64位sdk的dvs的没用过
nvshenxp 2012-04-06
  • 打赏
  • 举报
回复
up!!!!
nvshenxp 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]
[StructLayoutAttribute(LayoutKind.Sequential)]
结构前加这个, 结构体的子结构自己new出来, 保证回调函数的全局性, 还有把回调置为空试一下。
[/Quote]
恩,回调置为空,然后
/// <summary>
///向设备注册
///H264_DVR_API long CALL_METHOD H264_DVR_Login(char *sDVRIP, unsigned short wDVRPort, char *sUserName, char *sPassword,LPH264_DVR_DEVICEINFO lpDeviceInfo, int *error);
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_Login(string sDVRIP, ushort wDVRPort, string sUserName, string sPassword, ref H264_DVR_DEVICEINFO lpDeviceInfo, IntPtr error);

改为
/// <summary>
///向设备注册
///H264_DVR_API long CALL_METHOD H264_DVR_Login(char *sDVRIP, unsigned short wDVRPort, char *sUserName, char *sPassword,LPH264_DVR_DEVICEINFO lpDeviceInfo, int *error);
/// </summary>
[DllImport("netsdk.dll")]
public static extern int H264_DVR_Login(string sDVRIP, ushort wDVRPort, string sUserName, string sPassword, ref H264_DVR_DEVICEINFO lpDeviceInfo, ref int error);

就OK了!谢谢!
nvshenxp 2012-04-06
  • 打赏
  • 举报
回复
谢谢,大家,问题解决了,结贴
小志 2012-04-06
  • 打赏
  • 举报
回复
nuomitutu 2012-04-06
  • 打赏
  • 举报
回复
[StructLayoutAttribute(LayoutKind.Sequential)]
结构前加这个, 结构体的子结构自己new出来, 保证回调函数的全局性, 还有把回调置为空试一下。
nvshenxp 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
C++写的DLL有源代码吗?如果有的话可以将这段代码添加到C#工程中,然后在DLL中设置断点进行调试,这样你就知道问题出在哪了。
[/Quote]
没有源代码,所以这么郁闷。。。
liuyiuhui 2012-04-06
  • 打赏
  • 举报
回复
C++写的DLL有源代码吗?如果有的话可以将这段代码添加到C#工程中,然后在DLL中设置断点进行调试,这样你就知道问题出在哪了。
vinjent 2012-04-05
  • 打赏
  • 举报
回复
印象中試試這個做法, 在編譯環境中功能列
偵錯/例外狀況/Managed Debugging Assistants/CallbackOnCollectedDetegate(取消擲回)
偵錯/例外狀況/Managed Debugging Assistants/InvalidFunctionPointerInDelegate(取消擲回)
睡神在睡觉 2012-04-05
  • 打赏
  • 举报
回复
字符集的问题吧
[DllImport("netsdk.dll",EntryPoint = "H264_DVR_Init", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
EnForGrass 2012-04-05
  • 打赏
  • 举报
回复
一般这种问题很可能是参数不对应,仔细检查一下
nvshenxp 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
1、C#中进行结构定义时,须加[StructLayout(LayoutKind.Sequential]
2、fDisConnect回调函数在H264_DVR_Init调用完成后供dll使用,须使用HandleRef或GCHandle避免GC
建议楼主贴出H264_DVR_Init的C#调用相关代码
[/Quote]
其实我自己不是很清楚怎么调用,可能调用上面也有问题,我是参考网上看到的海康视频服务器的使用来调用的。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MonitorClient;
using System.Net.Sockets;
namespace MonitorClient
{
public partial class Form1 : Form
{

int curLoginID = -1;
NetSDK.fDisConnect fc;
int lRealHandle = -1;
public Form1()
{
InitializeComponent();

}
private void Form1_Load(object sender, EventArgs e)
{

fc = new NetSDK.fDisConnect(Connect);
NetSDK.H264_DVR_Init(fc, 1);
NetSDK.H264_DVR_SetConnectTime(3000,1);

}
private void button1_Click(object sender, EventArgs e)
{
H264_DVR_DEVICEINFO dfo = new H264_DVR_DEVICEINFO();
try
{
curLoginID = NetSDK.H264_DVR_Login("192.168.0.10", 34567, "admin", "", out dfo, IntPtr.Zero);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}


if (curLoginID == -1)
{
MessageBox.Show(string.Format("登录DVS失败,错误码: {0}", NetSDK.H264_DVR_GetLastError()), "登录DVS失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}


H264_DVR_CLIENTINFO cfo = new H264_DVR_CLIENTINFO();
cfo.hWnd = this.panel1.Handle;
cfo.nChannel = 2;
cfo.nComType = 1;
cfo.nMode = 0;
cfo.nStream = 1;
lRealHandle= NetSDK.H264_DVR_RealPlay(curLoginID, ref cfo);
if (lRealHandle == -1)
{
MessageBox.Show(string.Format("播放失败,错误码: {0}", NetSDK.H264_DVR_GetLastError()));
return;
}
}
private void Connect(int lLoginID, string pchDVRIP, int nDVRPort, uint dwUser)
{

lLoginID = curLoginID;
pchDVRIP = "192.168.0.10";
nDVRPort = 34567;
dwUser = 0;
}

}
}
WAN 2012-04-05
  • 打赏
  • 举报
回复
1、C#中进行结构定义时,须加[StructLayout(LayoutKind.Sequential]
2、fDisConnect回调函数在H264_DVR_Init调用完成后供dll使用,须使用HandleRef或GCHandle避免GC
建议楼主贴出H264_DVR_Init的C#调用相关代码
EnForGrass 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 1 楼 的回复:
一般这种问题很可能是参数不对应,仔细检查一下

参数问题的话最有可能出现在设备信息那个结构体的转换当中,但是,如果我不调用初始化函数就不会提示这个错误,所以我不知道是出现在哪边的。
[/Quote]
你最好一个个函数调试,四个函数一起调试不好找错
nvshenxp 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
印象中試試這個做法, 在編譯環境中功能列
偵錯/例外狀況/Managed Debugging Assistants/CallbackOnCollectedDetegate(取消擲回)
偵錯/例外狀況/Managed Debugging Assistants/InvalidFunctionPointerInDelegate(取消擲回)
[/Quote]

什么意思啊?
nvshenxp 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
一般这种问题很可能是参数不对应,仔细检查一下
[/Quote]
参数问题的话最有可能出现在设备信息那个结构体的转换当中,但是,如果我不调用初始化函数就不会提示这个错误,所以我不知道是出现在哪边的。
nvshenxp 2012-04-05
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
字符集的问题吧
[DllImport("netsdk.dll",EntryPoint = "H264_DVR_Init", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[/Quote]
改了还是会出现这个错误。

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧