海康SDK编程指南(C#二次开发版本)

摘要:
海康SDK编程指南目前使用的海康SDK包括IPC_SDK,Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息。本文仅对视频监控常用功能的使用进行说明,其它未实现功能请参看设备网络SDK使用手册和播放库编程指南V7.2。IPC_SDK编程指南(一)SDK的引用由于IPC_SDK没有SDK安装程序,所以需手工把下面图表中的DLL放入Debug或者Release文件夹的根目录下供程序调用,或者加入系统环境变量Path下。
海康SDK编程指南

目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息。本文仅对视频监控常用功能的使用进行说明,其它未实现功能请参看设备网络SDK使用手册播放库编程指南V7.2

IPC_SDK编程指南

(一) SDK的引用

由于IPC_SDK没有SDK安装程序,所以需手工把下面图表中的DLL放入Debug或者Release文件夹的根目录下供程序调用,或者加入系统环境变量Path下。

名称

版本号

说明

AudioIntercom.dll

1.1.0.5

AudioRender.dll

1.0.0.2

DsSdk.dll

6.0.10.922

gdiplus.dll

微软库

HCNetSDK.dll

4.3.0.6

网络功能调用,大量功能调用此库

OpenAL32.dll

PlayCtrl.dll

7.2.0.0

播放库,定制版本,增加返角回调及数据结构

QosControl.dll

1.0.0.1

StreamTransClient.dll

1.1.2.12

SuperRender.dll

1.0.1.0

SystemTransform.dll

2.4.0.3

设备信息转发,根据播放库修改过

(二) C#程序调用DLL中的非托管函数方法

1. 调用外部声明方法

首先在C#语言源程序中声明外部方法,其基本形式是:

[DLLImport(“DLL文件”)]

修饰符 extern 返回变量类型 方法名称 (参数列表)

例如:

using System.Runtime.InteropServices;

[DllImport("HCNetSDK.dll")]
public static extern bool NET_DVR_Init();

注意:

1) 需要在程序声明中使用System.Runtime.InteropServices命名空间。 DllImport只能放置在方法声明上。

2) DLL文件必须位于程序当前目录或系统定义的查询路径中(即:系统环境变量中Path所设置的路径)。

3) 返回变量类型、方法名称、参数列表一定要与DLL文件中的定义相一致。

4) 若要使用其它函数名,可以使用EntryPoint属性设置,如:[DllImport("user32.dll", EntryPoint="MessageBoxA")]

static extern int MsgBox(int hWnd, string msg, string caption, int type);

5) 其它可选的 DllImportAttribute 属性:

CharSet 指示用在入口点中的字符集,如:CharSet=CharSet.Ansi;

SetLastError 指示方法是否保留 Win32"上一错误",如:SetLastError=true;

ExactSpelling 指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配,

如:ExactSpelling=false;

PreserveSig指示方法的签名应当被保留还是被转换, 如:PreserveSig=true;

CallingConvention指示入口点的调用约定, 如:CallingConvention=CallingConvention.Winapi;

2. 参数数据类型转换

Win32 Types

CLR Type

char,INT8,SBYTE,CHAR

System.SByte

short,short int,INT16,SHORT

System.Int16

int,long,long int,INT32,LONG32,BOOL,INT

System.Int32

_int64,INT64,LONGLONG

System.Int64

unsigned char,UINT8,UCHAR,BYTE

System.Byte

unsigned short,UINT16,USHORT,WORD,ATOM,WCHAR,__wchar_t

System.UInt16

unsigned,unsigned int,UINT32,ULONG32,DWORD32,ULONG,DWORD,UINT

System.UInt32

unsigned __int64,UINT64,DWORDLONG,ULONGLONG

System.UInt64

float,FLOAT

System.Single

double,long double,DOUBLE

System.Double

BSTR

StringBuilder

LPCTSTR

StringBuilder

LPCWSTR

IntPtr

handle

IntPtr

hwnd

IntPtr

char *

string

int *

ref int

int &

ref int

void *

IntPtrs

unsigned char *

ref byte

BOOL ——

bool

DWORD

uint或int

注意:

  1. 指针做参数时在C#中一定要使用ref 或out关键字,尤其是结构体指针,要不会报内存读取错误
  2. 首先声明结构体 [StructLayoutAttribute(LayoutKind.Sequential)]
  3. 重写结构体的时候,之前有指明类型长度或数组长度的地方,也要进行相应的标注,要不也会导致内存错误

3. 重写结构体

例如:[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)],具体长度需参看SDK中改结构体的说明文档

或者

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64, ArraySubType = UnmanagedType.I1)]

4. 结构体与指针之间的转换

1) 结构体转换为指针

Hik.NET_DVR_IPPARACFG_V40 ipParaCfgV40 = new Hik.NET_DVR_IPPARACFG_V40();//初始化结构体结构体
Int32 size = Marshal.SizeOf(ipParaCfgV40);//返回结构体字节数
IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal(size);//定义指针字节数
Marshal.StructureToPtr(ipParaCfgV40, ptrIpParaCfgV40, false);//将结构体封装到内存指针中
//调用需要指针的方法
Marshal.FreeHGlobal(ptrIpParaCfgV40);//释放指针

2) 指针转换为结构体

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//实例化结构体
Int32 size = Marshal.SizeOf(cameraParamCfg );//获取结构体字节数
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//为指针分配空间
//调用获取指针的方法
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//把指针转换为结构体
Marshal.FreeHGlobal(ptrCfg);//释放指针

3) 指针转换为结构体精简写法

Int32 size = Marshal.SizeOf(typeof(Hik.NET_DVR_PTZPOS));
IntPtr ptrPTZ = Marshal.AllocHGlobal(size);
//调用获取指针的方法
Hik.NET_DVR_PTZPOS PTZPos = (Hik.NET_DVR_PTZPOS)Marshal.PtrToStructure(ptrPTZ, typeof(Hik.NET_DVR_PTZPOS));//指针转换为结构体
Marshal.FreeHGlobal(ptrPTZ);//释放指针

对第2点和第3点的说明:当一个方法的参数为一个结构体的指针时,并且执行方法后此指针会返回结构体信息时,可以有两种方式来初始化这个指针,第二种更为简洁些。

(三) SDK的调用

对IPC_SDK的C#封装类见附件Hik.cs,可参考此基础类文件进行程序功能编写。

1. 获取错误码

Hik.NET_DVR_GetLastError();//获取错误码

使用方式:如果每个非托管函数方法返回结果为false,则调用此方法获取错误码。

例如:

ret = Hik.NET_DVR_Init();
if (ret != true)
 throw new HikException(Hik.NET_DVR_GetLastError());//HikException为自定义异常调用类,用来解析错误码抛出异常

2. 登录

1) 用户注册

Hik.NET_DVR_Init();//初始化SDK,多次初始化会抛出错误
Hik.NET_DVR_SetConnectTime(2000, 1);//设置超时时间
Hik.NET_DVR_SetReconnect(10000, 1);//设置重连时间
Hik.NET_DVR_DEVICEINFO_V30 _deviceInfo = new Hik.NET_DVR_DEVICEINFO_V30();//登录参数结构体,可以返回设备信息
String userId = Hik.NET_DVR_Login_V30(IP,Port,UserName,Password,ref _deviceInfo);//登录后,获取用户ID和设备信息供后续方法调用

2) 用户注销

Hik.NET_DVR_StopRealPlay(_realHandle);//如果有预览视频,则根据其播放句柄关闭视频
Hik.NET_DVR_Logout(_userId);//根据用户ID注销用户登录
Hik.NET_DVR_Cleanup();//必须执行的释放IPC_SDK

3. 获取通道号

由于IPC_SDK同时支持IPC与NVR,所以两者获取通道号的方式有所不同。

1) 获取IPC设备通道号

如果Hik.NET_DVR_DEVICEINFO_V30结构体中byChanNum模拟通道数量属性值大于0,则代表登录设备为IPC设备,需要获取其模拟通道号byStartChan属性的值。每组模拟通道号范围为0-32。

for (Int32 i = 0; i < _deviceInfo.byChanNum; i++)//一个IPC设备可以设置多个模拟通道号,默认为一个模拟通道号
{
 Int channelId = _deviceInfo.byStartChan
}

2) 获取NVR设备通道号

如果Hik.NET_DVR_DEVICEINFO_V30结构体中byIPChanNum数字通道数量属性值大于0,则代表登录设备为NVR设备,需要获取其数字通道号,其获取方法要比获取IPC设备通道号复杂。每组数字通道号范围为33-64。

public void InfoIPChannel()
 {
 Hik.NET_DVR_IPPARACFG_V40 ipParaCfgV40 = new Hik.NET_DVR_IPPARACFG_V40();
 Int32 size = Marshal.SizeOf(ipParaCfgV40);
 IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal(size);
 Marshal.StructureToPtr(ipParaCfgV40, ptrIpParaCfgV40, false);
 UInt32 result = 0;
 Int32 groupNo = 0;
 Boolean ret = Hik.NET_DVR_GetDVRConfig(_userId, Hik.NET_DVR_GET_IPPARACFG_V40, groupNo, ptrIpParaCfgV40, (UInt32)size, ref result);//获取配置信息
 if (ret)
 {
 ipParaCfgV40 = (Hik.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(ptrIpParaCfgV40, typeof(Hik.NET_DVR_IPPARACFG_V40));
 byte byStreamType;
 for (Int32 i = 0; i < ipParaCfgV40.dwDChanNum; i++)
 {
 byStreamType = ipParaCfgV40.struStreamMode[i].byGetStreamType;
 size = Marshal.SizeOf(ipParaCfgV40.struStreamMode[i].uGetStream);
 switch (byStreamType)
 {
 //目前NVR仅支持直接从设备取流 NVR supports only the mode: get stream from device directly
 case 0:
 IntPtr ptrChanInfo = Marshal.AllocHGlobal(size);
 Marshal.StructureToPtr(ipParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfo, false);
 Hik.NET_DVR_IPCHANINFO _struChanInfo = (Hik.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(Hik.NET_DVR_IPCHANINFO));
 Int32 deviceId = _struChanInfo.byIPID + _struChanInfo.byIPIDHigh * 256 - groupNo * 64 - 1;
 if (deviceId == -1)
 continue;
 _channelInfoList.Add(new ChannelInfo() { DeviceID = deviceId, ChannelID = i + (Int32)ipParaCfgV40.dwStartDChan, State = (Int32)_struChanInfo.byEnable, IP = ipParaCfgV40.struIPDevInfo[i].struIP.sIpV4 });//获取数字通道信息封装到自定义通道类中
 Marshal.FreeHGlobal(ptrChanInfo);
 break;
 default:
 break;
 }
 }
 }
 Marshal.FreeHGlobal(ptrIpParaCfgV40);
 }

4. 预览

1) 初始化预览结构体

Hik.NET_DVR_PREVIEWINFO previewInfo = new Hik.NET_DVR_PREVIEWINFO();
previewInfo.lChannel = channelId;//预览的设备通道 the device channel number
previewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
previewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP 
previewInfo.hPlayWnd = IntPtr.Zero;//预览窗口,如果不使用回调显示视频流,则此处可以设置显示窗口句柄
previewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流

2) 获取实时视频流和视频句柄

_realHandle = Hik.NET_DVR_RealPlay_V40(UserId, ref previewInfo, realData, IntPtr.Zero);//返回实时流句柄供后续方法调用

参数说明:

UserID为登录后返回的用户句柄,

previewInfo为已实例化的预览结构体

realData为预览实时流回调函数,如果直接在窗口显示实时流而不通过回调方式,则此参数可以设置为null

3) 实时流回调函数的使用

/// <summary>
/// 预览实时流回调函数
/// </summary>
/// <param name="lRealHandle">当前的预览句柄</param>
/// <param name="dwDataType">数据类型:1系统头数据,2流数据(包括复合流或音视频分开的视频流数据),3音频数据</param>
/// <param name="pBuffer">存放数据的缓冲区指针</param>
/// <param name="dwBufSize">缓冲区大小</param>
/// <param name="pUser">用户数据</param>
public delegate void REALDATACALLBACK(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser);

注意:实例化实时流回调函数时,不能在方法内声明并实例化,否则会被回收机制提前释放实例化对象,导致程序错误。需要在最外部调用类中作为字段预先声明。例如:

private Hik.REALDATACALLBACK _callback;//实时流回调,作为字段声明
public override int IncreaseClient()
{
 if (_callback == null)
 _callback = new Hik.REALDATACALLBACK(RealDataCallBack);
 Hik.StartPlay(Hik.ChannelInfoList[0].ChannelID, _callback);//播放实时流视频
}

简易流程描述为实时流回调函数返回实时视频流,然后把实时视频流传入到播放库解码,通过播放库的两个回调函数来返回解析后的视频流和角度。角度回调信息的格式为我公司定制协议,具体内容参看角度信息私有数据格式,59个字节长度的16进制字符串。

private Hik.DECCBFUN _displayCallback;//解码回调
private Hik.ADDITIONDATACBFUN _additionDataDisplayCallback;//角度回调

获取播放库错误码

Int port;
PlayM4_GetPort(ref port);//首先需获取播放句柄
PlayM4_GetLastError(port);//获取播放库错误码

具体回调如下:

int port;播放库端口号 
switch (dwDataType)
{
 case 1: // sys head 系统头数据
 if (dwBufSize > 0)
 {
 //获取播放句柄 Get the port to play
 PlayM4_GetPort(ref _port);
 //设置流播放模式
 PlayM4_SetStreamOpenMode(_port, 0);
 //打开码流,送入头数据 Open stream
 PlayM4_OpenStream(_port, pBuffer, dwBufSize, 2 * 1024 * 1024);
 //设置显示缓冲区个数 
PlayM4_SetDisplayBuf(_port, 15);
 //设置解码回调函数,获取解码后音视频原始数据 Set callback function of decoded data
 PlayM4_SetDecCallBackEx(_port, displayFun, IntPtr.Zero, 0);
  //设置角度回调函数,获取解码前角度信息
 PlayM4_SetAdditionDataCallBack(_port, 0x1004, additionDataDisplayFun, IntPtr.Zero);
 //开始解码 Start to play 
PlayM4_Play(_port, IntPtr.Zero);//最后一个参数表示播放窗体的指针
 }
 break;
 case 2: // video stream data 视频流数据(包括复合流和音视频分开的视频流数据)
 if (dwBufSize > 0 && _port != -1)
 {
 for (Int32 i = 0; i < 999; i++)
 {
 //送入码流数据进行解码 Input the stream data to decode
 if (!PlayM4_InputData(_port, pBuffer, dwBufSize))
  Thread.Sleep(2);
 else
  break; 
}
 }
 break;
 default:
 if (dwBufSize > 0 && _port != -1)
 {
 //送入其他数据 Input the other data
 for (Int32 i = 0; i < 999; i++)
 {
 if (!PlayM4_InputData(_port, pBuffer, dwBufSize))
 Thread.Sleep(2);
 else
 break;
 }
 }
 break;
 }

4) 停止预览

Hik.NET_DVR_StopRealPlay(_realHandle);//_realHandle为播放句柄

5. 云台控制

1) 云台操作命令

 SET_PRESET = 8,// 设置预置点 
CLE_PRESET = 9,// 清除预置点 
Up = 21,/* 云台以SS的速度上仰 */
 Down = 22,/* 云台以SS的速度下俯 */
 Left = 23,/* 云台以SS的速度左转 */
 Right = 24,/* 云台以SS的速度右转 */
 UpLeft = 25,/* 云台以SS的速度上仰和左转 */
 UpRight = 26,/* 云台以SS的速度上仰和右转 */
 DownLeft = 27,/* 云台以SS的速度下俯和左转 */
 DownRight = 28,/* 云台以SS的速度下俯和右转 */
 Auto = 29,/* 云台以SS的速度左右自动扫描 */
 ZOOM_IN = 11,/* 焦距以速度SS变大(倍率变大) */
 ZOOM_OUT = 12,/* 焦距以速度SS变小(倍率变小) */
 FOCUS_NEAR = 13, /* 焦点以速度SS前调 */
 FOCUS_FAR = 14, /* 焦点以速度SS后调 */
 IRIS_OPEN = 15, /* 光圈以速度SS扩大 */
 IRIS_CLOSE = 16, /* 光圈以速度SS缩小 */
 GOTO_PRESET = 39/* 快球转到预置点 */

2) 云台操作方法

根据定制协议,云台控制速度为1-160。但是需保证球机的升级包版本为IPD_R3_STD_5.2.0_141111。

/// <summary>
/// 带速度的云台控制操作(需先启动图像预览)
/// </summary>
/// <param name="lRealHandle">NET_DVR_RealPlay_V40的返回值</param>
/// <param name="dwPTZCommand">云台控制命令</param>
/// <param name="dwStop">云台停止动作或开始动作:0- 开始;1- 停止</param>
/// <param name="dwSpeed">云台控制的速度,用户按不同解码器的速度控制值设置。取值范围[1,160]</param>
/// <returns>TRUE表示成功,FALSE表示失败</returns>
bool NET_DVR_PTZControlWithSpeed(int lRealHandle, uint dwPTZCommand, uint dwStop, uint dwSpeed);

6. 预置位

1) 预置位命令

 SET_PRESET = 8,// 设置预置点 
CLE_PRESET = 9,// 清除预置点 
GOTO_PRESET = 39// 转到预置点 

2) 预置位操作

/// <summary>
/// 设置预置位
/// </summary>
/// <param name="lRealHandle">NET_DVR_RealPlay_V40的返回值</param>
/// <param name="dwPTZPresetCmd">预置位控制命令</param>
/// <param name="dwPresetIndex">预置位编号最多支持255个预置点</param>
/// <returns>TRUE表示成功,FALSE表示失败</returns>
bool NET_DVR_PTZPreset(int lRealHandle, uint dwPTZPresetCmd, uint dwPresetIndex);

3) 反向操作

Hik.NET_DVR_PTZPreset(_realHandle, (uint)8, 33);

7. 获取前端参数配置

在设定某些配置时,需预先执行此方法来获取相关配置信息的结构体。

/// <summary>
/// 获取设备的配置信息
/// </summary>
/// <param name="lUserID">NET_DVR_Login_V30的返回值</param>
/// <param name="dwCommand">设备配置命令</param>
/// <param name="lChannel">通道号或者组号,不同的命令对应不同的取值</param>
/// <param name="lpOutBuffer">接收数据的缓冲指针</param>
/// <param name="dwOutBufferSize">接收数据的缓冲长度(以字节为单位),不能为0</param>
/// <param name="lpBytesReturned">实际收到的数据长度指针,不能为NULL</param>
/// <returns></returns>
bool NET_DVR_GetDVRConfig(int lUserID, uint dwCommand, int lChannel, IntPtr lpOutBuffer, uint dwOutBufferSize, ref uint lpBytesReturned);

具体调用见下面操作示例

8. 设置前端参数配置

/// <summary>
/// 设置设备的配置信息
/// </summary>
/// <param name="lUserID">NET_DVR_Login_V30的返回值</param>
/// <param name="dwCommand">设备配置命令</param>
/// <param name="lChannel">通道号或者组号,不同的命令对应不同的取值
<param>
/// <param name="lpInBuffer">输入数据的缓冲指针</param>
/// <param name="dwInBufferSize">输入数据的缓冲长度(以字节为单位)</param>
/// <returns></returns>
bool NET_DVR_SetDVRConfig(int lUserID, uint dwCommand, int lChannel, IntPtr lpInBuffer, uint dwInBufferSize);

具体调用见下面操作示例

9. 日夜切换

1) 设备配置命令

3369; //IPC设置CCD参数配置
3368; //IPC获取CCD参数配置

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//实例化前端参数结构体
Int32 nSize = Marshal.SizeOf(cameraParamCfg );//获取结构体空间大小
IntPtr ptrCfg = Marshal.AllocHGlobal(nSize);//设置指针大小
Hik.NET_DVR_GetDVRConfig(_userId,3368, _channelId, ptrCfg, (UInt32)nSize, ref dwReturn);//获取配置信息的指针
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//指针转换为数据结构
Marshal.FreeHGlobal(ptrCfg);//释放指针

4) 日夜切换命令

0白天
1夜晚
2自动

5) 日夜切换结构体

NET_DVR_DAYNIGHT struDayNight;/*日夜转换*/

6) 设置配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg=获取配置信息();
Int32 size = Marshal.SizeOf(cameraParamCfg);//获取结构体大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//设置指针空间大小
cameraParamCfg.struDayNight.byDayNightFilterType = (byte)日夜切换命令;
Marshal.StructureToPtr(cameraParamCfg, ptrCfg, false);//结构体转换为指针
Hik.NET_DVR_SetDVRConfig(_userId, 3369, _channelId, ptrCfg, (uint)size);//设置参数
Marshal.FreeHGlobal(ptrCfg);//释放指针

10. 透雾切换

1) 设备配置命令

3369; //IPC设置CCD参数配置
3368; //IPC获取CCD参数配置

2) 通道号或者组号

 ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//实例化前端参数结构体
Int32 nSize = Marshal.SizeOf(cameraParamCfg );//获取结构体空间大小
IntPtr ptrCfg = Marshal.AllocHGlobal(nSize);//设置指针大小
Hik.NET_DVR_GetDVRConfig(_userId,3368, _channelId, ptrCfg, (UInt32)nSize, ref dwReturn);//获取配置信息的指针
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//指针转换为数据结构
Marshal.FreeHGlobal(ptrCfg);//释放指针

4) 透雾切换命令

0关闭
2开启

5) 透雾切换结构体

NET_DVR_DEFOGCFG struDefogCfg;//透雾参数

6) 设置配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg=获取配置信息();
Int32 size = Marshal.SizeOf(cameraParamCfg);//获取结构体大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//设置指针空间大小
cameraParamCfg.struDefogCfg.byMode = (byte)透雾切换命令;
cameraParamCfg.struDefogCfg.byLevel = (byte)100;//透雾级别
Marshal.StructureToPtr(cameraParamCfg, ptrCfg, false);//结构体转换为指针
Hik.NET_DVR_SetDVRConfig(_userId, 3369, _channelId, ptrCfg, (uint)size);//设置参数
Marshal.FreeHGlobal(ptrCfg);//释放指针

11. 聚焦模式切换

1) 设备配置命令

 3306; //设置快球聚焦模式参数
 3305; //获取快球聚焦模式参数

2) 通道号或者组号

 ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_FOCUSMODE_CFG focusModeCfg = new Hik.NET_DVR_FOCUSMODE_CFG();//实例化聚焦模式结构体
Int32 size = Marshal.SizeOf(focusModeCfg);//获取结构体大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//设置指针空间大小
Hik.NET_DVR_GetDVRConfig(_userId, 3305, _channelId, ptrCfg, (UInt32)size, ref dwReturn);//获取聚焦模式信息的指针
focusModeCfg = (Hik.NET_DVR_FOCUSMODE_CFG)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_FOCUSMODE_CFG));//指针转换为聚焦模式结构体
Marshal.FreeHGlobal(ptrCfg);//释放指针

4) 聚焦模式切换命令

0自动
1手动
2半自动

5) 聚焦模式切换结构体

NET_DVR_FOCUSMODE_CFG

6) 设置配置信息

Hik.NET_DVR_FOCUSMODE_CFG focusModeCfg = 获取配置信息();
Int32 size = Marshal.SizeOf(focusModeCfg);//获取结构体大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//设置指针空间大小
focusModeCfg.byFocusMode = (byte)聚焦模式命令;
Marshal.StructureToPtr(focusModeCfg, ptrCfg, false);//结构体转换为指针
Hik.NET_DVR_SetDVRConfig(_userId, Hik.NET_DVR_SET_FOCUSMODECFG, _channelId, ptrCfg, (uint)size);//设置聚焦模式
Marshal.FreeHGlobal(ptrCfg);//释放指针

12. OSD字符设置

1) 设备配置命令

1030;//获取叠加字符操作命令
1031;//设置叠加字符操作命令

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_SHOWSTRING_V30 struShowStrCfg = new Hik.NET_DVR_SHOWSTRING_V30();//初始化叠加字符结构体
Int32 size = Marshal.SizeOf(struShowStrCfg);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针大小
Hik.NET_DVR_GetDVRConfig(_userId, 1030, _channelId, ptr, (UInt32)size, ref dwReturn);//获取配置信息
struShowStrCfg = (Hik.NET_DVR_SHOWSTRING_V30)Marshal.PtrToStructure(ptr, typeof(Hik.NET_DVR_SHOWSTRING_V30));//指针转换为结构体
Marshal.FreeHGlobal(ptr);//释放指针

4) 叠加字符结构体

NET_DVR_SHOWSTRINGINFO struStringInfo;/* 要显示的字符内容 */

说明:设置叠加字符需要为其属性赋值。

5) 设置配置信息

Hik.NET_DVR_SHOWSTRING_V30 struShowStrCfg =获取叠加字符配置信息();
Int32 size = Marshal.SizeOf(struShowStrCfg);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针空间大小
String osd = "海康智能监控视频一";
struShowStrCfg.struStringInfo[0].wShowString = 1;//1为显示,0为不显示
struShowStrCfg.struStringInfo[0].sString = osd;//叠加的字符串
struShowStrCfg.struStringInfo[0].wStringSize = (ushort)(osd.Length * 2);//字符串大小
struShowStrCfg.struStringInfo[0].wShowStringTopLeftX = 0;//坐标
struShowStrCfg.struStringInfo[0].wShowStringTopLeftY = 0;//坐标
Marshal.StructureToPtr(struShowStrCfg, ptr, false);//街头体转换为指针
Hik.NET_DVR_SetDVRConfig(_userId, 1031, _channelId, ptr, (UInt32)size);//设置配置信息
Marshal.FreeHGlobal(ptr);//释放指针

说明:可以叠加显示多个字符串。

13. 球机定位速度设置

1) 设备配置命令

3270;//获取PTZ基本参数信息
3271;//设置PTZ基本参数信息

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg = new Hik.NET_DVR_PTZ_BASICPARAMCFG();//初始化PTZ基本参数结构体
Int32 size = Marshal.SizeOf(basicParamCfg);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针大小
Hik.NET_DVR_GetDVRConfig(userId, 3270, _channelId, ptr, (UInt32)size, ref bytesReturned);//获取配置参数指针
basicParamCfg = (Hik.NET_DVR_PTZ_BASICPARAMCFG)Marshal.PtrToStructure(ptr, typeof(Hik.NET_DVR_PTZ_BASICPARAMCFG));//指针转换为结构体
Marshal.FreeHGlobal(ptr);//释放指针

4) 球机定位速度命令

1-8

5) 球机定位速度结构体

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg

6) 设置配置信息

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg = 获取配置信息();
Int32 size = Marshal.SizeOf(basicParamCfg);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针空间大小
basicParamCfg.byPresetSpeed = (byte)速度值;
Marshal.StructureToPtr(basicParamCfg, ptr, false);//结构体转换为指针
Hik.NET_DVR_SetDVRConfig(userId, 3271, _channelId, ptr, size);//设置配置信息
Marshal.FreeHGlobal(ptr);//释放指针

14. 获取球机转动范围

1) 设备配置命令

294;//云台获取PTZ范围

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

Hik.NET_DVR_PTZSCOPE PTZScope = new Hik.NET_DVR_PTZSCOPE();//初始化球机范围信息结构体
Int32 size = Marshal.SizeOf(PTZScope);//获取结构体空间大小
IntPtr ptrScope = Marshal.AllocHGlobal(size);//设置指针空间大小
Hik.NET_DVR_GetDVRConfig(_userId, 294, _channelId, ptrScope, (UInt32)size, ref result);//获取配置信息
PTZScope = (Hik.NET_DVR_PTZSCOPE)Marshal.PtrToStructure(ptrScope, typeof(Hik.NET_DVR_PTZSCOPE));//指针转换为结构体
Marshal.FreeHGlobal(ptrScope);//释放指针

4) 球机转动范围结构体

Hik.NET_DVR_PTZSCOPE PTZScope

15. 球机定位

使用球机定位功能前,需先设置球机定位速度和获取球机转动范围,再根据球机转动范围信息来操作球机定位功能。

1) 设备配置命令

292;//云台设置PTZ位置
293;//云台获取PTZ位置

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 获取配置信息

//用精简方式实现
Int32 size = Marshal.SizeOf(typeof(Hik.NET_DVR_PTZPOS));//获取球机位置信息结构体大小
IntPtr ptrPTZ = Marshal.AllocHGlobal(size);//设置指针空间大小
Hik.NET_DVR_GetDVRConfig(_userId, 293, _channelId, ptrPTZ, (UInt32)size, ref result);//获取球机位置配置信息
Hik.NET_DVR_PTZPOS PTZPos = (Hik.NET_DVR_PTZPOS)Marshal.PtrToStructure(ptrPTZ, typeof(Hik.NET_DVR_PTZPOS));//指针转换为结构体
Marshal.FreeHGlobal(ptrPTZ);//释放指针

4) 透雾切换结构体

Hik.NET_DVR_PTZPOS PTZPos

5) 设置配置信息

Hik.NET_DVR_PTZPOS PTZPos = 获取球机位置信息();
Int32 size = Marshal.SizeOf(PTZPos);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针空间大小
PTZPos.wAction = 1;//-表示定位PTZ参数
//本结构体中的wAction参数是设置时的操作类型,因此获取时该参数无效。实际显示的PTZ值是获取到的十六进制值的十分之一,如获取的水平参数P的值是0x1750,实际显示的P值为175度;获取到的垂直参数T的值是0x0789,实际显示的T值为78.9度;获取到的变倍参数Z的值是0x1100,实际显示的Z值为110度。
String temp = "0x" + Convert.ToString(horAngle * 10);//实际显示的PTZ值是获取到的十六进制值的十分之一,所以需要把输入的数值乘以10再拼成十六进制字符串
PTZPos.wPanPos = Convert.ToUInt16(temp, 16);//转换为16进制水平角度
if (pitAngle >= 0)//判断俯仰角度的正负。由于零方位角的设置不同,会导致出现负的俯仰角度,所以处理方式不同
 PTZPos.wTiltPos = Convert.ToUInt16("0x" + Convert.ToString(pitAngle * 10), 16);
else
 PTZPos.wTiltPos = Convert.ToUInt16("0x" + Convert.ToString((pitAngle + 360) * 10), 16);
PTZPos.wZoomPos = Convert.ToUInt16("0x" + Convert.ToString(viewAngle * 10), 16);
Marshal.StructureToPtr(PTZPos, ptr, false);//结构体转换为指针
Hik.NET_DVR_SetDVRConfig(_userId, 292, _channelId, ptr, (uint)size);//设置配置
Marshal.FreeHGlobal(ptr);//释放指针

16. 零方位角控制

1) 设备配置命令

3283;// 零方位角控制

2) 通道号或者组号

ChannelId//登录IPC设备时获取的通道号

3) 零方位角控制命令

SET = 0,//设置
GOTO = 1,//调用
CLE = 2//清除

4) 零方位角控制结构体

Hik.NET_DVR_INITIALPOSITIONCTRL initialPositionCtrl

5) 设置控制信息

Hik.NET_DVR_INITIALPOSITIONCTRL initialPositionCtrl = new Hik.NET_DVR_INITIALPOSITIONCTRL();//初始化零方位角控制结构体
Int32 size = Marshal.SizeOf(initialPositionCtrl);//获取结构体空间大小
IntPtr ptr = Marshal.AllocHGlobal(size);//设置指针大小
initialPositionCtrl.dwSize = (uint)size;//结构体大小
initialPositionCtrl.dwChan = (uint)_channelId;//播放通道号
initialPositionCtrl.byWorkMode = (byte)command;//零方位角控制命令
Marshal.StructureToPtr(initialPositionCtrl, ptr, false);//结构体转换为指针
Hik.NET_DVR_RemoteControl(_userId, (uint)3283, ptr, (uint)size);//零方位角控制
Marshal.FreeHGlobal(ptr);//释放指针

17. 录像回放

此功能需要硬盘录像机支持。需要先登录NVR设备。在登录和获取数字通道号后,根据设备所对应的通道号操作相关IPC设备的一些基础功能。

1) 设备配置命令

1;//开始播放
2;//停止播放
3;//暂停播放
4;//恢复播放
5;//快放
6;//慢放
7;//正常速度
8;//单帧放
9;//打开声音
10;//关闭声音
11;//调节音量
12;//改变文件回放的进度
13;//获取文件回放的进度
14;//获取当前已经播放的时间(按文件回放的时候有效)
15;//获取当前已经播放的帧数(按文件回放的时候有效)
16;//获取当前播放文件总的帧数(按文件回放的时候有效)
17;//获取当前播放文件总的时间(按文件回放的时候有效)
20;//丢B帧
24;//设置码流速度
25;//保持与设备的心跳(如果回调阻塞,建议2秒发送一次)
26;//按绝对时间定位
27;//获取按时间回放对应时间段内的所有文件的总长度
29;//倒放切换为正放
30;//正放切换为倒放
32;//设置转封装类型
33;//正放切换为倒放

2) 初始化录像回放结构体

Hik.NET_DVR_VOD_PARA struVodPara = new Hik.NET_DVR_VOD_PARA();//初始化录像回放结构体
struVodPara.dwSize = (uint)Marshal.SizeOf(struVodPara);//获取结构体空间大小
struVodPara.struIDInfo.dwChannel = (uint)_ipChannelId; //数字通道号 Channel number,海康设备数字通道号从33开始 
//struVodPara.hWnd = this.pictureBoxVideo.Handle;//不使用回调获取回放视频时,使用此属性设置回放窗口句柄
 struVodPara.hWnd = IntPtr.Zero;//使用回调获取回放视频时,需如此设置回放窗口句柄
//设置回放的开始时间 Set the starting time to search video files
struVodPara.struBeginTime.dwYear = (uint)dateTimeStart.Value.Year;
struVodPara.struBeginTime.dwMonth = (uint)dateTimeStart.Value.Month;
struVodPara.struBeginTime.dwDay = (uint)dateTimeStart.Value.Day;
struVodPara.struBeginTime.dwHour = (uint)dateTimeStart.Value.Hour;
struVodPara.struBeginTime.dwMinute = (uint)dateTimeStart.Value.Minute;
struVodPara.struBeginTime.dwSecond = (uint)dateTimeStart.Value.Second;
//设置回放的结束时间 Set the stopping time to search video files
struVodPara.struEndTime.dwYear = (uint)dateTimeEnd.Value.Year;
struVodPara.struEndTime.dwMonth = (uint)dateTimeEnd.Value.Month;
struVodPara.struEndTime.dwDay = (uint)dateTimeEnd.Value.Day;
struVodPara.struEndTime.dwHour = (uint)dateTimeEnd.Value.Hour;
struVodPara.struEndTime.dwMinute = (uint)dateTimeEnd.Value.Minute;
struVodPara.struEndTime.dwSecond = (uint)dateTimeEnd.Value.Second;

3) 获取录像回放播放句柄

目前根据需求只实现根据录像起止时间范围播放录像视频,其他功能请参考SDK功能说明文档。

//按时间回放 Playback by time
_realHandle = Hik.NET_DVR_PlayBackByTime_V40(_NVRUserId, ref struVodPara);// struVodPara为录像回放结构体

4) 录像数据回调函数的使用

/// <summary>
/// 录像数据回调函数 
/// </summary>
/// <param name="lPlayHandle">当前的录像播放句柄</param>
/// <param name="dwDataType">数据类型</param>
/// <param name="pBuffer">存放数据的缓冲区指针</param>
/// <param name="dwBufSize">缓冲区大小</param>
/// <param name="pUser">用户数据</param>
public delegate void PlayDataCallBack_V40(Int32 lPlayHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser);

此回调函数的使用方式与实时流回调函数的操作方式类似,都是获取视频流后,用播放库解码,返回角度信息和解码后的视频流。

Hik.NET_DVR_PlayBackControl_V40(_realHandle, 1, IntPtr.Zero, 0, IntPtr.Zero, ref iOutValue);//播放录像回放视频

5) 停止录像回放

Hik.NET_DVR_StopPlayBack(_realHandle)

18. 录像下载

1) 初始化录像下载结构体

Hik.NET_DVR_PLAYCOND struDownPara = new Hik.NET_DVR_PLAYCOND();//初始化录像下载结构体
struDownPara.dwChannel = (uint)_ipChannelId; //数字通道号 Channel number 
//设置下载的开始时间 Set the starting time
struDownPara.struStartTime.dwYear = (uint)dateTimeStart.Value.Year;
struDownPara.struStartTime.dwMonth = (uint)dateTimeStart.Value.Month;
struDownPara.struStartTime.dwDay = (uint)dateTimeStart.Value.Day;
struDownPara.struStartTime.dwHour = (uint)dateTimeStart.Value.Hour;
struDownPara.struStartTime.dwMinute = (uint)dateTimeStart.Value.Minute;
struDownPara.struStartTime.dwSecond = (uint)dateTimeStart.Value.Second;
//设置下载的结束时间 Set the stopping time
struDownPara.struStopTime.dwYear = (uint)dateTimeEnd.Value.Year;
struDownPara.struStopTime.dwMonth = (uint)dateTimeEnd.Value.Month;
struDownPara.struStopTime.dwDay = (uint)dateTimeEnd.Value.Day;
struDownPara.struStopTime.dwHour = (uint)dateTimeEnd.Value.Hour;
struDownPara.struStopTime.dwMinute = (uint)dateTimeEnd.Value.Minute;
struDownPara.struStopTime.dwSecond = (uint)dateTimeEnd.Value.Second;

2) 录像下载结构体

Hik.NET_DVR_PLAYCOND struDownPara

3) 录像下载

录像下载后默认保存格式为mp4。

_realHandle = Hik.NET_DVR_GetFileByTime_V40(_NVRUserId, sVideoFileName, ref struDownPara);
Plat_SDK编程指南

海康平台可以挂载多个NVR设备,调用NVR下挂载的IPC设备时,只需要在海康平台的设备设置中找到其摄像头ID即可。

(一) SDK的引用

具体引用方式,参见IPC_SDK的引用。由于海康平台技术人员提供的DLL文件过于繁杂,就不一一列出DLL的说明,详情参见IVMS_SDK文件夹目录。

(二) C#程序调用DLL中的非托管函数方法

详情参见C#程序调用DLL中的非托管函数方法

(三) SDK的调用

根据海康视频设备及平台使用的方案设计,只应用海康平台SDK的视频回调显示功能,其它功能暂不使用。对Plat_SDK的C#封装类见附件HikIVMS.cs,可参考此基础类文件进行程序功能编写。

1. 获取错误码

Plat_GetLastError(_userId);//获取错误码,userId为登录后获得的用户ID

使用方式:如果每个非托管函数方法返回结果不为0(正确),则调用此方法获取错误码。

例如:

Int32 ret = Plat_Init();
if (ret != 0)
 throw new HikIVMSException(Plat_GetLastError(_userId));// HikIVMSException为自定义异常调用类,用来解析错误码抛出异常

2. 登录

1) 用户注册

Int32 ret;
ret = Plat_Init();//platformSDK初始化
if (ret != 0)
 throw new HikIVMSException(Plat_GetLastError(_userId));
IntPtr ptrIP = Marshal.StringToHGlobalAnsi(uri.Host);//IP
IntPtr ptrUserName = Marshal.StringToHGlobalAnsi(a[0]);//用户名
IntPtr ptrPassword = Marshal.StringToHGlobalAnsi(a[1]);//密码
IntPtr ptrPort = Marshal.StringToHGlobalAnsi(uri.Port.ToString());//端口号
_userId = Plat_LoginCMS(ptrIP, ptrUserName, ptrPassword, ptrPort, 0);//登录
//释放指针
Marshal.FreeHGlobal(ptrIP);
Marshal.FreeHGlobal(ptrUserName);
Marshal.FreeHGlobal(ptrPassword);
Marshal.FreeHGlobal(ptrPort);

2) 用户注销

//如果存在播放的视频,也就是_streamHandle播放句柄>0,则先停止播放视频
Plat_StopVideo(_streamHandle);
Plat_LogoutCMS(_userId);//注销用户
Plat_Free();//释放SDK,必须执行

3. 预览

1) 播放预览

/// <summary>
/// 播放实时视频(开始预览/回放)
/// </summary>
/// <param name="url">预览或回放的播放路径,由Plat_QueryRealStreamURL或Plat_QueryRecordFile</param>
/// <param name="hWnd">播放窗口句柄,如果为空,则不播放</param>
/// <param name="userHandle">用户ID</param>
/// <param name="streamCallback">视频码流接收回调函数指针,如果回调函数为NULL则不给码流</param>
/// <returns>>=0成功,返回实时视频句柄,错误时返回-1</returns>
Int32 Plat_PlayVideo(String url, IntPtr hWnd, Int32 userHandle, fStreamCallback streamCallback, IntPtr user);

例如:

_streamHandle = Plat_PlayVideo(cameraId, IntPtr.Zero, _userId, callback, IntPtr.Zero);

注意:此函数的第一个参数,在应用中只需要传入摄像机ID即可。

2) 实时流回调函数的使用

/// <summary>
/// 实时流回调
/// </summary>
/// <param name="handle">Plat_PlayVideo返回的句柄</param>
/// <param name="data">接收视频码流数据缓冲区指针</param>
/// <param name="size">接收视频码流数据字节数</param>
/// <param name="user">用户数据</param>
public delegate void fStreamCallback(Int32 handle, IntPtr data, UInt32 size, IntPtr user, UInt32 dataType);

其调用方式与IPC_SDK中回调实时视频流的方式相同,都是调用播放库解码,然后返回角度信息和解码后的视频。详情参见IPC_SDK预览功能说明

示例如下:

private HikIVMS.fStreamCallback _callback;
private HikIVMS.DECCBFUN _displayCallback;//解码回调
private HikIVMS.ADDITIONDATACBFUN _additionDataDisplayCallback;//角度回调
if (_callback == null)
_callback = new HikIVMS.fStreamCallback(StreamCallback);
if (_displayCallback == null)
 _displayCallback = new HikIVMS.DECCBFUN(DecCallbackFUN);
if (_additionDataDisplayCallback == null)
 _additionDataDisplayCallback = new HikIVMS.ADDITIONDATACBFUN(AdditionDataCallBackFUN);
Hik.Play(cameraCode, _callback);

注意:Plat的回调函数与IPC回调函数中唯一的区别在于数据类型的定义不同,IPC的系统头数据类型为1,视频流数据类型为2;Plat系统头数据类型为0,视频流数据类型为1,仅此区别,其它相同。

免责声明:文章转载自《海康SDK编程指南(C#二次开发版本)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vue脚手架配置插件image-webpack-loader 图片压缩浅析前端常见文件下载的9种场景:Blob基础知识/组成/Blob URL、a标签下载、showSaveFilePicker API下载(兼容性差)、FileSaver.js库下载、Zip下载(JSZip库)、附件形式下载(设置Content-Disposition)、base64格式下载(需转为blob)、分块传输下载、HTTP范围请求下载、大文件分块并行下载下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ubuntu 终端命令速查表

 1、man: shell命令的说明指南   该命令代表manual,提供一个给定命令的说明指南。   用法:man <shell command>   用例:man ls   上述命令请求命令‘ls’的说明页,如下图:    2、ls: 列出目录内容   该命令列举出在当前目录下的文件和文件夹的内容。   用法:ls   上述指令的输入如下图...

Linux 内核 hlist 详解

在Linux内核中,hlist(哈希链表)使用非常广泛。本文将对其数据结构和核心函数进行分析。 和hlist相关的数据结构有两个:hlist_head 和 hlist_node //hash桶的头结点struct hlist_head {   struct hlist_node *first;//指向每一个hash桶的第一个结点的指针};//hash桶的...

超全!iOS 面试题汇总

作者:Job_Yang 之前看了很多面试题,感觉要不是不够就是过于冗余,于是我将网上的一些面试题进行了删减和重排,现在分享给大家。(题目来源于网络,侵删) 1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现多...

Zabbix 中文使用手册

一、Zabbix简介 详情参考“企业监控利器-zabbix”http://waringid.blog.51cto.com/65148/904201。 二、Zabbix使用 2.1 Zabbix框架介绍 在浏览器中输入http://192.168.0.189进入监控软件登陆界面(图二),登陆用户名和密码为network,登陆后的界面如图三所示。 图二:登录...

002输入子系统驱动

输入子系统概念介绍(第十三课/第一节) 回顾第三个驱动程序(中断方式的按键驱动程序)和测试程序,发现有一些缺点:这个驱动程序没办法用在别人写的现成的应用程序上(比如:QT),因为别人写的应用程序肯定不会来打开你这个"/dev/third_chrdev"。别人打开的是一些现成的设备(比如:/dev/tty),甚至别人都不打开设备,而是直接调用 scanf()...

gdb调试命令的使用及总结

gdb调试命令的使用及总结 gdb是一个在UNIX环境下的命令行调试工具。如果需要使用gdb调试程序,请在gcc时加上-g选项。下面的命令部分是简化版,比如使用l代替list等等。 1.基本命令 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 fram...