gpt4 book ai didi

c++ - Delphi 如何在另一个函数中使用回调函数作为参数?

转载 作者:太空宇宙 更新时间:2023-11-03 10:25:23 26 4
gpt4 key购买 nike

我想将 C++ 代码转换为 Delphi。 C++ 代码从相机(海康威视)获取流。这是我要转换为 Delphi 的 C++ 代码:

    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;

}

这是我的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 (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';

我定义了海康威视摄像头播放视频的回调函数(MyRealDataCallBack),并将此函数作为另一个函数(NET_DVR_RealPlay_V40)的输入参数

最佳答案

您正在尝试使用 Form 类的非静态方法作为回调。非静态方法有一个隐藏的 Self 参数,相机 API 将无法填充该参数(除非您创建代理 stub ,这是本问题范围之外的高级技术)。您需要从回调中删除该参数,方法是将回调声明为独立过程,或者将其声明为 class static 方法。无论哪种方式,如果您需要访问 Form 对象的成员(例如 TPanel),您可以使用回调的 dwUser 参数将 Form 的对象指针传递给回调。

尝试这样的事情:

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.

关于c++ - Delphi 如何在另一个函数中使用回调函数作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37652218/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com