**
SOLVED
**
Thanks to the Rob for bringing light to my problem.
Create a global var on component unit fDict Implement 3 methods, one to add, one to remove and one to retrive; making the main class create , clear and destroy the global var to avoid memory leaks making the connectin function of TDispositivo to feed the fDict making the callback to retrive and move on. making the disconnect function of TDispositivo to remove the reference in fDict keeping it updated
**
EDIT
**
I found my crash error, i´m implementing the dll inside a component class and try to declare the callback procedures inside the class using
TSnapRev = procedure(XXXXX) of object stdcall;
... private procedure callbacksnapshot(XXXXX); stdcall; ...
CLIENT_SetSnapRevCallBack(callbackSnapshot,FSDKUSer);
the callbacksnapshot was triggered but raising a accesse violation after.
O realize the order of variables returned was always misplaced, then i change my approuch moving the callbacksnapshot procedure out of the class and changing type declaration like this:
Type TSnapRev = procedure(XXXXX); stdcall;
TDispositivo = class private end;
procedure callbacksnapshot(XXXXX); stdcall;
... CLIENT_SetSnapRevCallBack(@callbackSnapshot,FSDKUSer); ...
now the callback triggeing, the order of variables are right and no access violation after, BUT, i need to invoke some functions (events, etc) from my TDispositivo instance or from the owner of TDispositivo instance, in a outside procedure i can´t.
How can i do this into my class ?
i had tryed declare a variable FSDKSnap : TRevSap (when TRevSap is a type of object) but got the same erros or miplaced vars and access violations
**
ORIGINAL
**
Keep working on my Dahua dll convertion to Delphi. Now i'm stuck in a callback, actually in a definition of the type used.
There is the cpp code in header
#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);
Looking to the cpp code, it defined BYTE as unsigned char, so mapping to Delphi (Byte), UINT mapping to Cardinal.
The structure was mapped to Cardinal as well.
---> First question HERE
The callback fSnapRev has (BYTE *pBuf) so i suppose is a pointer to byte (Delphi PByte) and i suspect here is the problem. A buffer with so little memory is not right, maybe a array of bytes or array of pansichar. How can i do know that ? like try and miss ? I accept suggestions.
The RevLen and Encode Type was mapped to Cardinal.
There is the cpp code from demo application.
//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);
}
}
In OnOnePicture the first code is to define the path to image file be stored, then write the buffer in a file stream. if the buffer and size comes from pBuf and RevLen, then i can write this on a TMemoryStream and assign to TJpegImage but still do not know what pBuf really is.
Another ocuard thing is the data, revLen returns value 10 and is too small to be a byte length of the image.
My Delphi Code
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;
When i call SDKSnapshot, i got the "showmessage" placed in callbackfunction with the values, but im debug mode i got infinite access violation, on Release mode the application close after the showmessage.
I try to do nothing on callback but still getting access violation and termination.
I´m wondering if my problem is the declaration of the callback procedure, pBuf.