C++ CPP到Delphi的转换
** 解决 ** 感谢Rob帮我解决了问题 在组件单元fDict上创建全局var 实施三种方法,一种添加,一种删除,一种检索; 使主类创建、清除和销毁全局变量以避免内存泄漏 使TDispositivo的连接功能为fDict供电 进行回调以重试并继续。 使用TDispositivo的断开功能删除fDict中的参考,并保持其更新 ** 编辑 ** 我发现了崩溃错误,我正在组件类中实现dll,并尝试使用 TSnapRev=对象stdcall的过程(XXXXX) 。。。 私有的 程序回调快照(XXXXX);stdcall; 客户端_SetSnapRevCallBack(callbackSnapshot,FSDKUSer) callbacksnapshot已触发,但在触发后引发访问冲突 O意识到返回变量的顺序总是放错位置,然后我改变了方法,将callbacksnapshot过程移出类,并改变类型声明,如下所示: 类型 TSnapRev=程序(XXXXX);stdcall TDispositivo=类 私有的 结束 程序回调快照(XXXXX);stdcall 。。。 CLIENT_SetSnapRevCallBack(@callbackSnapshot,FSDKUSer); 现在回调触发了,变量的顺序正确,之后没有访问冲突,但是,我需要从我的TDispositivo实例或TDispositivo实例的所有者调用一些函数(事件等),在一个外部过程中我不能 我怎样才能在课堂上做到这一点 我曾尝试声明一个变量FSDKSnap:TRevSap(当TRevSap是一种对象类型时),但得到了相同的错误或miplaced vars以及访问冲突 ** 原创的 ** 继续进行我的大华dll到Delphi的转换。现在我被困在回调中,实际上是在所用类型的定义中 标题中有cpp代码C++ CPP到Delphi的转换,c++,delphi,dll,C++,Delphi,Dll,** 解决 ** 感谢Rob帮我解决了问题 在组件单元fDict上创建全局var 实施三种方法,一种添加,一种删除,一种检索; 使主类创建、清除和销毁全局变量以避免内存泄漏 使TDispositivo的连接功能为fDict供电 进行回调以重试并继续。 使用TDispositivo的断开功能删除fDict中的参考,并保持其更新 ** 编辑 ** 我发现了崩溃错误,我正在组件类中实现dll,并尝试使用 TSnapRev=对象stdcall的过程(XXXXX) 。。。 私有的 程序回调快照(XXXXX
#define BYTE unsigned char
#define UINT unsigned int
// Snapshot parameter structure
typedef struct _snap_param
{
unsigned int Channel; // Snapshot channel
unsigned int Quality; // Image quality:level 1 to level 6
unsigned int ImageSize; // Video size;0:QCIF,1:CIF,2:D1
unsigned int mode; // Snapshot mode;0:request one frame,1:send out requestion regularly,2: Request consecutively
unsigned int InterSnap; // Time unit is second.If mode=1, it means send out requestion regularly. The time is valid.
unsigned int CmdSerial; // Request serial number
unsigned int Reserved[4];
} SNAP_PARAMS, *LPSNAP_PARAMS;
// Snapshot callback function original shape
// Encode Type 10: jpeg 0: number i frame of mpeg4
typedef void (CALLBACK *fSnapRev)(LLONG lLoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser);
// Set snapshot callback function
CLIENT_NET_API void CALL_METHOD CLIENT_SetSnapRevCallBack(fSnapRev OnSnapRevMessage, LDWORD dwUser);
// Snapshot request
CLIENT_NET_API BOOL CALL_METHOD CLIENT_SnapPicture(LLONG lLoginID, SNAP_PARAMS par);
查看cpp代码,它将BYTE定义为无符号字符,因此映射到Delphi(BYTE),UINT映射到Cardinal
该结构也被映射到Cardinal
--->第一个问题
回调fSnapRev有(BYTE*pBuf),所以我想是一个指向BYTE(Delphi PByte)的指针,我怀疑这就是问题所在。内存太少的缓冲区是不正确的,可能是字节数组或pansichar数组。我怎么知道?像尝试和错过?我接受建议
RevLen和Encode类型映射到Cardinal
这是演示应用程序中的cpp代码
//First part of the method to initialize the dll,
BOOL ret = CLIENT_Init(DisConnectFunc, (LDWORD)this);
if (ret)
{
CLIENT_SetSnapRevCallBack(SnapPicRet,(LDWORD)this);
//here defining the callback
CLIENT_SetAutoReconnect(ReConnectFunc, (LDWORD)this);
}
else
{
MessageBox(ConvertString("initialize SDK failed!"), ConvertString("prompt"));
}
//the callback
void CALLBACK SnapPicRet(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial,
LDWORD dwUser)
{
CCapturePictureDlg *pThis = (CCapturePictureDlg*)dwUser;
pThis->OnOnePicture(ILoginID,pBuf,RevLen,EncodeType,CmdSerial);
}
void CCapturePictureDlg::OnOnePicture(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, UINT
CmdSerial)
{
//Get file path
char path[1000];
int filelen = GetModuleFileName(NULL,path,1000);
int i = filelen;
while(path[i]!='\\')
{
i--;
}
path[i + 1] = '\0';
//Get file name
CString filepath(path);
CString filename = "mpeg4.JPG";
CString strfile = filepath + filename;
char *pFileName = strfile.GetBuffer(200);
/* Save image original file */
FILE *stream;
if( (stream = fopen((const char*) pFileName, "wb")) != NULL )
{
int numwritten = fwrite( pBuf, sizeof( char ), RevLen, stream );
fclose( stream );
}
/*Veirfy image encode type. If it is an I frame of mpeg4,then call I frame to decode to BMP to display.*/
if ( EncodeType == 0)
{
//int iRet = IFrameToBmp("tmp.bmp",pFileName);
//if (iRet == 1)
//{
// ShowBitmap("tmp.bmp");
//}
}
else if (EncodeType == 10)
{
//ShowBitmap(pFileName);
ShowSnapImage(pFileName);
}
}
在OnOnePicture中,第一个代码是定义要存储的图像文件的路径,然后在文件流中写入缓冲区。如果缓冲区和大小来自pBuf和RevLen,那么我可以将其写入TMemoryStream并分配给TJpegImage,但仍然不知道pBuf到底是什么
另一个ocuard内容是数据,revLen返回值10,太小,无法作为图像的字节长度
我的Delphi代码
TSnapRev = procedure(lLoginID: Integer; pBuf: PByte; RevLen: Cardinal; EncodeType: Cardinal; CmdSerial: DWORD; dwUser: DWORD) of object stdcall;
// Snapshot parameter structure
PSnapParams = ^TSnapParams;
TSnapParams = record
Channel: Cardinal; // Snapshot channel
Quality: Cardinal; // Image quality:level 1 to level 6
ImageSize: Cardinal; // Video size;0:QCIF,1:CIF,2:D1
mode: Cardinal; // Snapshot mode;0:request one frame,1:send out requestion regularly,2: Request consecutively
InterSnap: Cardinal; // Time unit is second.If mode=1, it means send out requestion regularly. The time is valid.
CmdSerial: Cardinal; // Request serial number
Reserved: array[0..3] of Cardinal;
end;
// Snapshot request
function CLIENT_SnapPicture(lLoginID: Integer; par: TSnapParams): Boolean; stdcall; external 'dhnetsdk.dll';
procedure callbackSnapshot(lLoginID: Integer; pBuf: PByte; RevLen: Cardinal; EncodeType: Cardinal; CmdSerial: DWORD; dwUser: DWORD); stdcall;
//Part of my initDll function
FInicializado := CLIENT_Init(callbackDis,FSDKUser);
if FInicializado then
begin
CLIENT_SetSnapRevCallBack(callbackSnapshot,FSDKUSer);
end;
Result := FInicializado;
//Snapshot wrapper procedure
procedure TDispositivo.SDKSnapshot;
var
sIn: TSnapParams;
begin
ZeroMemory(@sIn, SizeOf(sIn));
With sIn do
begin
Channel := 1;
mode := 0;
CmdSerial := 0;
if not CLIENT_SnapPicture(FLoginHandler,sIn) then
begin
doErro(999,'Não foi possível tirar o snapshot');
end;
end;
end;
//the callback implementation
procedure TDispositivo.callbackSnapshot(lLoginID: Integer; pBuf: PByte; RevLen: Cardinal; EncodeType: Cardinal; CmdSerial: DWORD; dwUser: DWORD);
var
F: TMemoryStream;
jpg : TJpegImage;
begin
Showmessage('Tamanho do buffer: ' + SizeOf(pBuf).ToString + #13 +
'RevLen: ' + RevLen.ToString + #13 +
'Tipo: ' + EncodeType.ToString + #13 +
'CmdSerial: ' + CmdSerial.ToString
);
F := TMemoryStream.Create;
jpg := TJPEGImage.Create;
Try
F.Write(pBuf,RevLen);
//F.Write(pBuf^,RevLen);
F.Position:= 0;
jpg.LoadFromStream(F);
fOwner.doSnapshot(self,jpg);
Finally
FreeAndNil(F);
FreeAndNil(jpg);
End;
end;
当我调用SDKSnapshot时,我得到了放置在callbackfunction中的“showmessage”值,但在im调试模式下,我得到了无限访问冲突,在发布模式下,应用程序在showmessage之后关闭
我尝试在回调时不做任何事情,但仍然会遇到访问冲突和终止
我想知道我的问题是否在于回调过程pBuf的声明。我怀疑您的LLoginId应该是Int64。。LLON将在源平台的编译器方言/系统包含中定义。(见:) 您的错误表明这些参数包含垃圾(见下文),如果它们的顺序不正确,就会发生这种情况-这可能意味着您的参数大小错误(因此LLoginId没有从堆栈读取所有值,它后面的所有变量都将损坏) 您可以尝试制作LLogin Int64,或者如果您想进一步研究,可以尝试以下方法: 您似乎成功地调用了回调例程,但例程中接收到的变量不正确。(您说您只有revLen 10,访问冲突错误表明pBuf可能指向垃圾) 您已经将例程声明为stdcall,这应该是正确的,参数将按照正常的“C”约定在堆栈上传递 如果中断例程的条目并在CPU视图中查看,您应该看到变量是从堆栈中读取的,并确定每个变量都设置正确。您应该能够将pBuf的地址放入内存窗口,并确定它是否指向JPEG ssignature中的JPEG数据
您还可以查看堆栈的内存转储,检查已传递给您的内容,并查看是否可以确定所需变量的实际位置。我怀疑您的LLoginId应该是Int64。。LLON将在源平台的编译器方言/系统包含中定义。(见:) 您的错误表明这些参数包含垃圾(见下文),如果它们的顺序不正确,就会发生这种情况-这可能意味着您的参数大小错误(因此LLoginId没有从堆栈读取所有值,它后面的所有变量都将损坏) 您可以尝试制作LLogin Int64,或者如果您想进一步研究,可以尝试以下方法: 您似乎成功地调用了回调例程,但例程中接收到的变量不正确。(您说您只有revLen 10,访问冲突错误表明pBuf可能指向垃圾) 您已经将例程声明为stdcall,这应该是正确的,参数将按照正常的“C”约定在堆栈上传递 如果中断例程的条目并在CPU视图中查看,您应该会看到变量是从堆栈中读取的,并且