Delphi如何在另一个函数中使用回调函数作为参数? < >我想把C++代码转换成Delphi。C++代码从相机(海康威视)中获取数据流。这是我想转换成Delphi的C++代码:< /P> void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void* dwUser) { HWND hWnd = GetConsoleWindow(); switch (dwDataType) { case NET_DVR_SYSHEAD: //System head if (!PlayM4_GetPort(&lPort)) //Get unused port { break; } if (dwBufSize > 0) { if (!PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME)) { break; } if (!PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024 * 1024)) { break; } if (!PlayM4_Play(lPort, hWnd)) //Start play { break; } } case NET_DVR_STREAMDATA: //Stream data if (dwBufSize > 0 && lPort != -1) { if (!PlayM4_InputData(lPort, pBuffer, dwBufSize)) { break; } } } } int _tmain(int argc, _TCHAR* argv[]) { NET_DVR_Init(); NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30("193.160.101.1", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return 0; } LONG lRealPlayHandle; NET_DVR_PREVIEWINFO struPlayInfo = { 0 }; struPlayInfo.hPlayWnd = NULL; //If need to decode, please set it valid. If want to get stream data only, it can be set to NULL struPlayInfo.lChannel = 1; //Preview channel NO. //struPlayInfo.dwStreamType = 0; //0-main stream, 1-sub stream, 2-stream3, 3-stream4. struPlayInfo.dwLinkMode = 0; //0-TCP mode, 1-UDP mode, 2-Multi-play mode, 3-RTP mode, 4-RTP/RTSP, 5-RTSP/HTTP lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, fRealDataCallBack, NULL) return 0; } void CALLBACK fRealDataCallBack(长lRealHandle、DWORD DWDATATATYPE、BYTE*pBuffer、DWORD dwBufSize、void*dwUser) { HWND HWND=GetConsoleWindow(); 开关(dwDataType) { 案例网络\u DVR\u系统头://系统头 如果(!PlayM4_GetPort(&lPort))//获取未使用的端口 { 打破 } 如果(dwBufSize>0) { 如果(!PlayM4_设置流模式(lPort,Stream_REALTIME)) { 打破 } 如果(!PlayM4_OpenStream(lPort、pBuffer、dwBufSize、1024*1024)) { 打破 } 如果(!PlayM4_Play(lPort,hWnd))//开始播放 { 打破 } } 案例网络\u DVR\u STREAMDATA://流数据 如果(dwBufSize>0&&lPort!=-1) { 如果(!PlayM4_InputData(lPort、pBuffer、dwBufSize)) { 打破 } } } } int _tmain(int argc,_TCHAR*argv[] { NET_DVR_Init(); 网络DVR设备信息V30结构设备信息; lUserID=NET\u DVR\u Login\u V30(“193.160.101.1”、8000、“admin”、“12345”和struDeviceInfo); if(lUserID0,则 开始 如果不是(播放M4_设置流模式(lPort,Stream_REALTIME)),则 开始 出口 终止 如果不是(PlayM4_OpenStream(lPort、pBuffer、dwBufSize、1024*1024)),则 开始 出口 终止 如果不是(播放M4\u播放(lPort,hPlayWnd)),则 开始 出口 终止 如果dwDataType=NET\u DVR\u STREAMDATA,则 开始 如果(dwBufSize>0)和(lPort-1),则 开始 如果不是(PlayM4_输入数据(lPort、pBuffer、dwBufSize)),则 开始 出口 终止 终止 终止 终止 终止 终止 程序TForm1.btnPlayClickClick(发送方:TObject); 变量 lRealPlayHandle:长柄; 开始 lRealPlayHandle:=NET\u DVR\u RealPlay\u V40(iLoginID,struPlayInfo,MyRealDataCallBack\u V30,null); 终止 函数NET\u DVR\u RealPlay\u V40(lUserID:LongInt;var lpPreviewInfo:TNET\u DVR\u PREVIEWINFO;RealDataCallBack\u V30:fRealDataCallBack\u V30;pUser:Pointer):LongInt;stdcall;外部'HCNetSDK.dll'名称'NET_DVR_RealPlay_V40';
这是我的Delphi代码Delphi如何在另一个函数中使用回调函数作为参数? < >我想把C++代码转换成Delphi。C++代码从相机(海康威视)中获取数据流。这是我想转换成Delphi的C++代码:< /P> void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void* dwUser) { HWND hWnd = GetConsoleWindow(); switch (dwDataType) { case NET_DVR_SYSHEAD: //System head if (!PlayM4_GetPort(&lPort)) //Get unused port { break; } if (dwBufSize > 0) { if (!PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME)) { break; } if (!PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024 * 1024)) { break; } if (!PlayM4_Play(lPort, hWnd)) //Start play { break; } } case NET_DVR_STREAMDATA: //Stream data if (dwBufSize > 0 && lPort != -1) { if (!PlayM4_InputData(lPort, pBuffer, dwBufSize)) { break; } } } } int _tmain(int argc, _TCHAR* argv[]) { NET_DVR_Init(); NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30("193.160.101.1", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return 0; } LONG lRealPlayHandle; NET_DVR_PREVIEWINFO struPlayInfo = { 0 }; struPlayInfo.hPlayWnd = NULL; //If need to decode, please set it valid. If want to get stream data only, it can be set to NULL struPlayInfo.lChannel = 1; //Preview channel NO. //struPlayInfo.dwStreamType = 0; //0-main stream, 1-sub stream, 2-stream3, 3-stream4. struPlayInfo.dwLinkMode = 0; //0-TCP mode, 1-UDP mode, 2-Multi-play mode, 3-RTP mode, 4-RTP/RTSP, 5-RTSP/HTTP lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, fRealDataCallBack, NULL) return 0; } void CALLBACK fRealDataCallBack(长lRealHandle、DWORD DWDATATATYPE、BYTE*pBuffer、DWORD dwBufSize、void*dwUser) { HWND HWND=GetConsoleWindow(); 开关(dwDataType) { 案例网络\u DVR\u系统头://系统头 如果(!PlayM4_GetPort(&lPort))//获取未使用的端口 { 打破 } 如果(dwBufSize>0) { 如果(!PlayM4_设置流模式(lPort,Stream_REALTIME)) { 打破 } 如果(!PlayM4_OpenStream(lPort、pBuffer、dwBufSize、1024*1024)) { 打破 } 如果(!PlayM4_Play(lPort,hWnd))//开始播放 { 打破 } } 案例网络\u DVR\u STREAMDATA://流数据 如果(dwBufSize>0&&lPort!=-1) { 如果(!PlayM4_InputData(lPort、pBuffer、dwBufSize)) { 打破 } } } } int _tmain(int argc,_TCHAR*argv[] { NET_DVR_Init(); 网络DVR设备信息V30结构设备信息; lUserID=NET\u DVR\u Login\u V30(“193.160.101.1”、8000、“admin”、“12345”和struDeviceInfo); if(lUserID0,则 开始 如果不是(播放M4_设置流模式(lPort,Stream_REALTIME)),则 开始 出口 终止 如果不是(PlayM4_OpenStream(lPort、pBuffer、dwBufSize、1024*1024)),则 开始 出口 终止 如果不是(播放M4\u播放(lPort,hPlayWnd)),则 开始 出口 终止 如果dwDataType=NET\u DVR\u STREAMDATA,则 开始 如果(dwBufSize>0)和(lPort-1),则 开始 如果不是(PlayM4_输入数据(lPort、pBuffer、dwBufSize)),则 开始 出口 终止 终止 终止 终止 终止 终止 程序TForm1.btnPlayClickClick(发送方:TObject); 变量 lRealPlayHandle:长柄; 开始 lRealPlayHandle:=NET\u DVR\u RealPlay\u V40(iLoginID,struPlayInfo,MyRealDataCallBack\u V30,null); 终止 函数NET\u DVR\u RealPlay\u V40(lUserID:LongInt;var lpPreviewInfo:TNET\u DVR\u PREVIEWINFO;RealDataCallBack\u V30:fRealDataCallBack\u V30;pUser:Pointer):LongInt;stdcall;外部'HCNetSDK.dll'名称'NET_DVR_RealPlay_V40';,c++,delphi,C++,Delphi,这是我的Delphi代码 procedure TForm1.MyRealDataCallBack_V30(lRealHandle:Longint;dwDataType:DWORD;pBuffer:PByte;dwBufSize,dwUser:DWORD); stdcall; begin hPlayWnd:=Panel1.Handle; if dwDataType = NET_DVR_SYSHEAD then begin if (
procedure TForm1.MyRealDataCallBack_V30(lRealHandle:Longint;dwDataType:DWORD;pBuffer:PByte;dwBufSize,dwUser:DWORD); stdcall;
begin
hPlayWnd:=Panel1.Handle;
if dwDataType = NET_DVR_SYSHEAD then
begin
if (not(PlayM4_GetPort(lPort))) then
begin
Exit;
end;
if dwBufSize > 0 then
begin
if not(PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME)) then
begin
Exit;
end;
if not(PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024*1024)) then
begin
Exit;
end;
if not(PlayM4_Play(lPort,hPlayWnd)) then
begin
Exit;
end;
if dwDataType = NET_DVR_STREAMDATA then
begin
if (dwBufSize > 0) and (lPort <> -1) then
begin
if not(PlayM4_InputData(lPort, pBuffer, dwBufSize)) then
begin
Exit
end;
end;
end;
end;
end;
end;
procedure TForm1.btnPlayClickClick(Sender: TObject);
var
lRealPlayHandle :Longint;
begin
lRealPlayHandle:=NET_DVR_RealPlay_V40(iLoginID,struPlayInfo,MyRealDataCallBack_V30,null);
end;
function NET_DVR_RealPlay_V40(lUserID: LongInt;var lpPreviewInfo: TNET_DVR_PREVIEWINFO; RealDataCallBack_V30:fRealDataCallBack_V30;pUser:Pointer): LongInt;stdcall; external 'HCNetSDK.dll' name'NET_DVR_RealPlay_V40';
procedure TForm1.MyRealDataCallBack_V30(lRealHandle:Longint;dwDataType:DWORD;pBuffer:PByte;dwBufSize,dwUser:DWORD);stdcall;
开始
hPlayWnd:=面板1.手柄;
如果dwDataType=NET\u DVR\u SYSHEAD,则
开始
如果(不是(PlayM4_GetPort(lPort)),则
开始
出口
终止
如果dwBufSize>0,则
开始
如果不是(播放M4_设置流模式(lPort,Stream_REALTIME)),则
开始
出口
终止
如果不是(PlayM4_OpenStream(lPort、pBuffer、dwBufSize、1024*1024)),则
开始
出口
终止
如果不是(播放M4\u播放(lPort,hPlayWnd)),则
开始
出口
终止
如果dwDataType=NET\u DVR\u STREAMDATA,则
开始
如果(dwBufSize>0)和(lPort-1),则
开始
如果不是(PlayM4_输入数据(lPort、pBuffer、dwBufSize)),则
开始
出口
终止
终止
终止
终止
终止
终止
程序TForm1.btnPlayClickClick(发送方:TObject);
变量
lRealPlayHandle:长柄;
开始
lRealPlayHandle:=NET\u DVR\u RealPlay\u V40(iLoginID,struPlayInfo,MyRealDataCallBack\u V30,null);
终止
函数NET\u DVR\u RealPlay\u V40(lUserID:LongInt;var lpPreviewInfo:TNET\u DVR\u PREVIEWINFO;RealDataCallBack\u V30:fRealDataCallBack\u V30;pUser:Pointer):LongInt;stdcall;外部'HCNetSDK.dll'名称'NET_DVR_RealPlay_V40';
我为从海康威视摄像头播放视频定义了回调函数(MyRealDataCallBack),并将此函数用作另一个函数(NET\u DVR\u RealPlay\u V40)中的输入参数。您不能在此处使用表单方法,您需要常规过程:
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType,
BYTE *pBuffer, DWORD dwBufSize, void* dwUser)
应该是
procedure fRealDataCallBack(lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall;
或者使用静态类过程
type
TMyClass = class
....
class procedure fRealDataCallBack(lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall; static;
您的NET\u DVR\u RealPlay\u V40
是使用类型化回调参数声明的,因此您需要在NET\u DVR\u RealPlay\u V40
之前声明回调函数的类型:
fRealDataCallBack_V30 = procedure (lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall;
您不能在此处使用form方法,您需要常规程序:
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType,
BYTE *pBuffer, DWORD dwBufSize, void* dwUser)
应该是
procedure fRealDataCallBack(lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall;
或者使用静态类过程
type
TMyClass = class
....
class procedure fRealDataCallBack(lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall; static;
您的NET\u DVR\u RealPlay\u V40
是使用类型化回调参数声明的,因此您需要在NET\u DVR\u RealPlay\u V40
之前声明回调函数的类型:
fRealDataCallBack_V30 = procedure (lRealHandle : LongInt; dwDataType: DWORD;
pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall;
您正在尝试使用表单类的非静态方法作为回调。非静态方法有一个隐藏的
Self
参数,照相机API将无法填充该参数(除非创建代理存根,这是一种超出本问题范围的高级技术)。您需要从回调中删除该参数,可以将回调声明为独立过程,也可以将其声明为类static
方法。无论哪种方式,如果需要访问表单对象的成员(如TPanel
),都可以使用回调的dwUser
参数将表单的对象指针传递给回调
试着这样做:
interface
type
TForm1 = class(TForm)
Panel1: TPanel;
btnPlay: TButton;
...
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnPlayClick(Sender: TObject);
...
private
lRealPlayHandle: LONG;
lPort: LONG;
iLoginID: LONG;
struDeviceInfo: TNET_DVR_DEVICEINFO_V30;
struPlayInfo: TNET_DVR_PREVIEWINFO;
...
procedure MyRealDataCallBack_V30(lRealHandle: LONG; dwDataType: DWORD; pBuffer: PByte; dwBufSize: DWORD);
...
end;
implementation
function NET_DVR_Init: BOOL; stdcall; external 'HCNetSDK.dll' name 'NET_DVR_Init';
function NET_DVR_Cleanup: BOOL; external 'HCNetSDK.dll' name 'NET_DVR_Cleanup';
function NET_DVR_RealPlay_V40(lUserID: LONG; var lpPreviewInfo: TNET_DVR_PREVIEWINFO; RealDataCallBack_V30: fRealDataCallBack_V30; pUser: Pointer): LONG; stdcall; external 'HCNetSDK.dll' name 'NET_DVR_RealPlay_V40';
// other DVR function declaration as needed...
procedure ActualRealDataCallBack_V30(lRealHandle: LONG; dwDataType: DWORD; pBuffer: PByte; dwBufSize: DWORD; dwUser: Pointer); stdcall;
begin
TForm1(dwUser).MyRealDataCallBack_V30(lRealHandle, dwDataType, pBuffer, dwBufSize);
end;
procedure TForm1.MyRealDataCallBack_V30(lRealHandle: LONG; dwDataType: DWORD; pBuffer: PByte; dwBufSize: DWORD);
begin
case dwDataType of
NET_DVR_SYSHEAD:
begin
if not PlayM4_GetPort(lPort) then
Exit;
if (dwBufSize > 0) then
begin
if not PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME) then
Exit;
if not PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024*1024) then
Exit;
if not PlayM4_Play(lPort, Panel1.Handle) then
Exit;
end;
end;
NET_DVR_STREAMDATA:
begin
if (dwBufSize > 0) and (lPort <> -1) then
begin
if not PlayM4_InputData(lPort, pBuffer, dwBufSize) then
Exit;
end;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
err: Integer;
begin
NET_DVR_Init;
iLoginID := NET_DVR_Login_V30('193.160.101.1', 8000, 'admin', '12345', struDeviceInfo);
if (iLoginID < 0) then
begin
err := NET_DVR_GetLastError;
NET_DVR_Cleanup;
raise Exception.CreateFmt('Login error, %d', [err]);
end;
struPlayInfo.hPlayWnd := 0; //If need to decode, please set it valid. If want to get stream data only, it can be set to NULL
struPlayInfo.lChannel := 1; //Preview channel NO.
//struPlayInfo.dwStreamType := 0; //0-main stream, 1-sub stream, 2-stream3, 3-stream4.
struPlayInfo.dwLinkMode := 0; //0-TCP mode, 1-UDP mode, 2-Multi-play mode, 3-RTP mode, 4-RTP/RTSP, 5-RTSP/HTTP
lPort := ...;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
NET_DVR_Cleanup;
end;
procedure TForm1.btnPlayClick(Sender: TObject);
begin
lRealPlayHandle := NET_DVR_RealPlay_V40(iLoginID, struPlayInfo, ActualRealDataCallBack_V30, Self);
end;
end.
接口
类型
TForm1=类(TForm)
小组1:TPanel;
BTN显示:t按钮;
...
过程表单创建(发送方:ToObject);
销毁程序表(发送方:TObject);
程序btnPlayClick(发件人:ToObject);
...
私有的
lRealPlayHandle:长;
L端口:长;
长的;
StrucDeviceInfo:TNET\u DVR\u DEVICEINFO\u V30;
struPlayInfo:TNET\u DVR\u PREVIEWINFO;
...
过程MyRealDataCallBack_V30(lRealHandle:LONG;dwDataType:DWORD;pBuffer:PByte;dwBufSize:DWORD);
...
终止
实施
函数NET\u DVR\u Init:BOOL;stdcall;外部'HCNetSDK.dll'名称'NET_DVR_Init';
功能网络\u DVR\u清理:BOOL;外部'HCNetSDK.dll'名称'NET_DVR_Cleanup';
功能网络