下面的C++介面,我用DELPHI對接,呼叫時報記憶體例外,麻煩各位大俠幫忙看一下:
C++介面定義:
struct STUMsgProperty 2 {
char m_szSourceUserID[MR 2_MAXLEN_ADDR];
char m_szSourceAppID[MR 2_MA XLEN_ADDR];
char m_szDestUserID[MR 2_MAXLEN_ADDR];
char m_szDestAppID[MR 2_MAXLEN_ADDR];
char m_szPkgID[MR 2_MAXLEN_PKGID];
char m_szCorrPkgID[MR 2_MAXLEN_PKGID];
char m_szUserData 1[MR 2_MAXLEN_USERDATA];
char m_szUserData2[MR 2_MAXLEN_USERDATA];
unsigned char m_ucFlag;
unsigned char m_uc Biz Type;
unsigned char m_ucPriority;
unsigned char m_ucSensitiveLevel;
char m_szMsgType[MR2_MAXLEN_MSGTYPE];
};
int _stdcall Mr 2Receive3(void* pHandle, char** ppsPkg, int * piOutPkgLen, int* piErrSXCode, STUMsgProperty 2* pMsgPropery, int iMillSecTimeo) ;
引數 說明
pHandle [in] 連接句柄。
ppsPkg [out] 雙指標,回傳包所向的記憶體。
piOutPkgLen [out] 接收到的訊息包實際長度。
piErrSXCode[out] 交換錯誤的原因碼.
pMsgPropery [in/out] 輸入將作為接收條件,輸出是接收到的包屬性。
iMillSecTimeo [in] 以毫秒為單位的接收最大時間。
Delphi代碼:
type
pSTUMsgProperty2 = ^TSTUMsgProperty2;
TSTUMsgProperty2 = record
m_szSourceUserID: array[1..MR2_MAXLEN_ADDR] of AnsiChar;
m_szSourceAppID: array[1..MR2_MAXLEN_ADDR] of AnsiChar;
m_szDestUserID: array[1..MR2_MAXLEN_ADDR] of AnsiChar;
m_szDestAppID: array[1..MR2_MAXLEN_ADDR] of AnsiChar;
m_szPkgID: array[1..MR2_MAXLEN_PKGID] of AnsiChar;
m_szCorrPkgID: array[1..MR2_MAXLEN_PKGID] of AnsiChar;
m_szUserData1: array[1..MR2_MAXLEN_USERDATA] of AnsiChar;
m_szUserData2: array[1..MR2_MAXLEN_USERDATA] of AnsiChar;
m_ucFlag: word;
m_ucBizType: word;
m_ucPriority: word;
m_ucSensitiveLevel: word;
m_szMsgType: array[1..MR2_MAXLEN_MSGTYPE] of AnsiChar;
end;
type
TMr2RecvFunc = function(_pMr2InitHandle: PHandle; const ppsPkg: PPAnsiChar; piOutPkgLen: Pinteger; piErrSXCode: Pinteger; pMsgPropery: pSTUMsgProperty2; iMillSecTimeo: integer):integer;stdcall;
function Mr2Receive: Integer;
var
pMr2Recv: TMr2RecvFunc;
FileStream: TFileStream;
FileBuffer: PPAnsiChar;
piOutPkgLen, piErrSXCode: pinteger;
pMsgPropery: pSTUMsgProperty2;
MsgPropery: TSTUMsgProperty2;
begin
Result := -1;
if pMr2InitHandle = nil then
begin
ShowMessage('請先初始化Mr2!');
Exit;
end;
if not Assigned(@pMr2Recv) then
@pMr2Recv := GetProcAddress(Mr2Handle, 'Mr2Receive3');
if Assigned(@pMr2Recv) then
begin
new(pMsgPropery);
Result := pMr2Recv(pMr2InitHandle, FileBuffer,piOutPkgLen, piErrSXCode, pMsgPropery, 2000);//這一步報記憶體寫例外
Dispose(pMsgPropery);
end;
end;
uj5u.com熱心網友回復:
TMr2RecvFunc = function(_pMr2InitHandle: PHandle; var ppsPkg: PPAnsiChar; piOutPkgLen: Pinteger; piErrSXCode: Pinteger; pMsgPropery: pSTUMsgProperty2; iMillSecTimeo: integer):integer;stdcall;uj5u.com熱心網友回復:
雙指標可以定義成^PCharuj5u.com熱心網友回復:
就是PPChar嘍?
賦值有什么要注意的么?
uj5u.com熱心網友回復:
指標引數可以轉化為變參,從而(形式上)脫去一級指標:int _stdcall Mr 2Receive3(void* pHandle, char** ppsPkg, int * piOutPkgLen, int* piErrSXCode, STUMsgProperty 2* pMsgPropery, int iMillSecTimeo) ;
TMr2RecvFunc = function(var _pMr2InitHandle: THandle; var ppsPkg: PAnsiChar; var piOutPkgLen: integer; var piErrSXCode: integer; var pMsgPropery: TSTUMsgProperty2; iMillSecTimeo: integer):integer;stdcall;
uj5u.com熱心網友回復:
TMr2RecvFunc = function(_pMr2InitHandle: PHandle; var ppsPkg: PAnsiChar; var piOutPkgLen: integer; var piErrSXCode: integer; var pMsgPropery: TSTUMsgProperty2; iMillSecTimeo: integer):integer;stdcall;
function Mr2Receive: Integer;
var
pMr2Recv: TMr2RecvFunc;
FileBuffer: PAnsiChar;
piOutPkgLen, piErrSXCode: integer;
MsgPropery: TSTUMsgProperty2;
begin
Result := -1;
if not Assigned(@pMr2Recv) then
@pMr2Recv := GetProcAddress(Mr2Handle, 'Mr2Receive3');
if Assigned(@pMr2Recv) then
begin
GetMem(FileBuffer,4096);
new(pMsgPropery);
try
Result := pMr2Recv(pMr2InitHandle, FileBuffer,piOutPkgLen, piErrSXCode, MsgPropery, 2000);
except
end;
freeMem(FileBuffer);
Dispose(pMsgPropery);
end;
end;
上面的代碼還是報錯,是初始化有問題么?
uj5u.com熱心網友回復:
pMr2InitHandle應該先有一個初始化程序吧,諸如有個openxxx函式回傳一個handle。uj5u.com熱心網友回復:
pMr2InitHandle是全域變數,已經有值的。
pMr2InitHandle = pMr2Init(ConfigMsg.AppID, ConfigMsg.AppPasswd, nil, @ConfigMsg.STUConnInfo, 2, PAnsiChar(''));
uj5u.com熱心網友回復:
pMr2Init回傳值是一個指標?uj5u.com熱心網友回復:
是的,發送資料、斷開連接的介面都需要用到這個值,呼叫時沒有發現問題。
但是我用pMr2InitHandle^取到的值是1,不知道是什么原因。
uj5u.com熱心網友回復:
以下藍色部分是C++的DEMO,用的MR2RECEIVE1:
typedef int (WINAPI MR2RECEIVE1)(void*, char**, int*, STUMsgProperty2*, int);
typedef int (WINAPI MR2RECEIVE3)(void*, char**, int*, int*, STUMsgProperty2*, int);
unsigned __stdcall RecvThrd(void *pvParam)
{
int iLastGetOk = 0;
for(;;)
{
STUMsgProperty2 oMsgPropery;
memset(&oMsgPropery, '\0', sizeof(STUMsgProperty2));
int iRecvPkgLen = 0;
char* psPkg = NULL;
int iRet = Mr2Receive1(g_pHandle, &psPkg, &iRecvPkgLen, &oMsgPropery, 1000);
if(iRet==0)
{
g_ltLastTimeRecv = time(NULL);
++g_iRecvCount;
if(g_iRecvCount%100==0)
{
printf("recv ok: PkgContent[%s]\n, pkgID[%s], src[%s.%s], dest[%s.%s], pkgLen[%d], CorrPkgID[%s], UserData1[%s], UserData2[%s] \n", psPkg, oMsgPropery.m_szPkgID, oMsgPropery.m_szSourceUserID, oMsgPropery.m_szSourceAppID, oMsgPropery.m_szDestUserID, oMsgPropery.m_szDestAppID, iRecvPkgLen, oMsgPropery.m_szCorrPkgID, oMsgPropery.m_szUserData1, oMsgPropery.m_szUserData2);
printf("client recv count[%d]\n", g_iRecvCount);
}
#ifndef MR_CLIENT
STUMsgProperty2 oMsgProperySend;
memset(&oMsgProperySend, '\0', sizeof(STUMsgProperty2));
strcpy(oMsgProperySend.m_szDestUserID, oMsgPropery.m_szSourceUserID);
strcpy(oMsgProperySend.m_szDestAppID, oMsgPropery.m_szSourceAppID);
strcpy(oMsgProperySend.m_szCorrPkgID, oMsgPropery.m_szPkgID);
strcpy(oMsgProperySend.m_szUserData1, oMsgPropery.m_szUserData1);
strcpy(oMsgProperySend.m_szUserData2, oMsgPropery.m_szUserData2);
oMsgProperySend.m_ucFlag = 0;
int iRet = Mr2Send(g_pHandle, psPkg, iRecvPkgLen, &oMsgProperySend, 2000);
#endif
Mr2Receive1_FreeBuf(psPkg);
}
else
{
MySleep(500);
}
}
return 0;
}
我現在想在DELPHI里呼叫MR2RECEIVE3,跟MR2RECEIVE1比就多了一個引數,麻煩再幫忙看一下哈。
uj5u.com熱心網友回復:
這里g_pHandle是一個指標:int iRet = Mr2Receive1(g_pHandle, &psPkg, &iRecvPkgLen, &oMsgPropery, 1000);
那么:
TMr2RecvFunc = function(_pMr2InitHandle: pointer; var ppsPkg: PAnsiChar; var piOutPkgLen: integer; var piErrSXCode: integer; var pMsgPropery: TSTUMsgProperty2; iMillSecTimeo: integer):integer;stdcall;
uj5u.com熱心網友回復:
@DelphiGuy 發私信了,麻煩幫忙看一下哈。謝謝!真的很著急。
uj5u.com熱心網友回復:
#11的宣告應該是沒有問題的,只是這個
int iRet = Mr2Receive1(g_pHandle, &psPkg, &iRecvPkgLen, &oMsgPropery, 1000);
g_pHandle是怎么得到的還得看他的例子代碼,可能是你獲取的不對。
uj5u.com熱心網友回復:
這個是C++ DEMO中的初始化程序:
typedef void *(WINAPI MR2INIT)(const char*, const char*, int, const STUConnInfo2*, void *);
void* g_pHandle = NULL;
int main(int argc, char* argv[])
{
if (!LoadDll())
{
printf("load mrapi.dll error.\n");
return -1;
}
string ssSourceUserID, ssSourceAppID, ssDestUserID, ssDestAppID;
string ssName1 = "FTCSTEST91";
string ssName2 = "app8";
string ssName3 = "FTCSTEST92";
string ssName4 = "app6";
#ifdef MR_CLIENT
ssSourceUserID = ssName1;
ssSourceAppID = ssName2;
ssDestUserID = ssName3;
ssDestAppID = ssName4;
#else
ssSourceUserID = ssName3;
ssSourceAppID = ssName4;
ssDestUserID = ssName1;
ssDestAppID = ssName2;
#endif
g_ltLastTimeRecv = time(NULL);
string ssMyPasswd = "1";
string *pUserData = new string("hello");
STUConnInfo2 oConnInfo[2];
memset(&oConnInfo, 0, 2*sizeof(STUConnInfo2));
if(argc<2) strcpy(oConnInfo[0].m_szMRIP, "127.0.0.1");
else strcpy(oConnInfo[0].m_szMRIP, argv[1]);
oConnInfo[0].m_usMRPort = 1001;
strcpy(oConnInfo[1].m_szMRIP, "127.0.0.1");
oConnInfo[1].m_usMRPort = 3001;
g_pHandle = Mr2Init(ssSourceAppID.c_str(), ssMyPasswd.c_str(), NULL, &oConnInfo, 2, pUserData);
if(g_pHandle==NULL) return -1;
/*
STUMsgProperty2 oOnRecvMsgPropery;
memset(&oOnRecvMsgPropery, 0, sizeof(STUMsgProperty2));
strcpy(oOnRecvMsgPropery.m_szCorrPkgID, "<EMPTY>");
Mr2Init2(&g_pHandle, ssSourceAppID.c_str(), ssMyPasswd.c_str(), &oOnRecvMsgPropery, (int)OnReceive, &oConnInfo, 2, pUserData, 1);
if(g_pHandle==NULL) return -1;
*/
if(_beginthreadex(NULL, 0, RecvThrd, NULL, 0, NULL)==0)
{
printf("create thread failed\n");
return -1;
}
printf("\n");
MySleep(2000);
g_ltLastTimeRecv = time(NULL);
#ifdef MR_CLIENT
#else
for(;;MySleep(1000))
{
}
#endif
Mr2Destroy(g_pHandle);
printf("End\n");
return 0;
}
下面是DELPHI代碼:
type TMr2InitFunc = function(const psAppID: PAnsiChar; const psPasswd:PAnsiChar; OnReceive:PInteger; const pArrConnInfo:pSTUConnInfo2; iArrConnInfoCount: Integer; pvUserData:PAnsiChar):Pointer;stdcall;
function Mr2Init: Pointer;
var
pMr2Init: TMr2InitFunc;
begin
Result := nil;
if Mr2Handle = 0 then
begin
PrintLog('請先加載mrapi.dll!');
Exit;
end;
@pMr2Init := GetProcAddress(Mr2Handle, 'Mr2Init');
if Assigned(@pMr2Init) then
begin
GetConfigMsg;
Result := pMr2Init(ConfigMsg.AppID, ConfigMsg.AppPasswd, nil, @ConfigMsg.STUConnInfo, 2, PAnsiChar(''));
end;
end;
uj5u.com熱心網友回復:
原型typedef void *(WINAPI MR2INIT)(const char*, const char*, int, const STUConnInfo2*, void *);
和實際呼叫
g_pHandle = Mr2Init(ssSourceAppID.c_str(), ssMyPasswd.c_str(), NULL, &oConnInfo, 2, pUserData);
對不上啊。
type TMr2InitFunc = function(const psAppID: PAnsiChar; const psPasswd:PAnsiChar; OnReceive:PInteger; const pArrConnInfo:pSTUConnInfo2; iArrConnInfoCount: Integer; pvUserData:PAnsiChar):Pointer;stdcall;
是根據什么翻譯的?
uj5u.com熱心網友回復:
1. 介面檔案定義(delph宣告是根據這個來的):
void* _stdcall Mr2Init(const char* psAppID, const char* psPasswd, int (*OnRe ceive 2)(const char* psPkg, int iPkgLe n, const STUMsgProperty 2* pMsgPropery , void* pvUserData), const STUConnInfo 2* pArrC onnInfo , int iArrConnInfoCount , void* pvUserData);
int _stdcall Mr2Receive3(void* pHandle, char** ppsPkg, int * piOutPkgLen, int* piErrSXCode, STUMsgProperty 2* pMsgPropery, int iMillSecTimeo) ;
2. C++ DEMO代碼:
宣告:
typedef void *(WINAPI MR2INIT)(const char*, const char*, int, const STUConnInfo2*, void *);
typedef int (WINAPI MR2RECEIVE3)(void*, char**, int*, int*, STUMsgProperty2*, int);
變數定義
MR2INIT *Mr2Init;
MR2RECEIVE3 *Mr2Receive3;
HINSTANCE m_ghDll;
void* g_pHandle = NULL;
加載DLL
m_ghDll = ::LoadLibrary(MRAPI_DLL) ;
if (m_ghDll == NULL)
{
printf(“error: can not find (mrapi.dll).”) ;
return bRet ;
}
Mr2Init = (MR2INIT *)::GetProcAddress(m_ghDll, "Mr2Init") ;
if (Mr2Init == NULL)
{
printf(“error: can not find Mr2Init(mrapi.dll)”) ;
::FreeLibrary(m_ghDll) ;
m_ghDll = NULL ;
return bRet ;
}
Mr2Receive3 = (MR2RECEIVE3 *)::GetProcAddress(m_ghDll, "Mr2Receive3") ;
if (Mr2Receive3 == NULL)
{
printf(“error: can not find Mr2Receive3(mrapi.dll)”) ;
::FreeLibrary(m_ghDll) ;
m_ghDll = NULL ;
return bRet ;
}
主程式
string ssSourceUserID, ssSourceAppID, ssDestUserID, ssDestAppID;
string ssName1 = "FTCSTEST91";
string ssName2 = "app8";
string ssName3 = "FTCSTEST92";
string ssName4 = "app6";
#ifdef MR_CLIENT
ssSourceUserID = ssName1;
ssSourceAppID = ssName2;
ssDestUserID = ssName3;
ssDestAppID = ssName4;
#else
ssSourceUserID = ssName3;
ssSourceAppID = ssName4;
ssDestUserID = ssName1;
ssDestAppID = ssName2;
#endif
g_ltLastTimeRecv = time(NULL);
string ssMyPasswd = "1";
string *pUserData = new string("hello");
STUConnInfo2 oConnInfo[2];
memset(&oConnInfo, 0, 2*sizeof(STUConnInfo2));
if(argc<2) strcpy(oConnInfo[0].m_szMRIP, "127.0.0.1");
else strcpy(oConnInfo[0].m_szMRIP, argv[1]);
oConnInfo[0].m_usMRPort = 1001;
strcpy(oConnInfo[1].m_szMRIP, "127.0.0.1");
oConnInfo[1].m_usMRPort = 3001;
g_pHandle = Mr2Init(ssSourceAppID.c_str(), ssMyPasswd.c_str(), NULL, &oConnInfo, 2, pUserData);
if(g_pHandle==NULL) return -1;
/*
STUMsgProperty2 oOnRecvMsgPropery;
memset(&oOnRecvMsgPropery, 0, sizeof(STUMsgProperty2));
strcpy(oOnRecvMsgPropery.m_szCorrPkgID, "<EMPTY>");
Mr2Init2(&g_pHandle, ssSourceAppID.c_str(), ssMyPasswd.c_str(), &oOnRecvMsgPropery, (int)OnReceive, &oConnInfo, 2, pUserData, 1);
if(g_pHandle==NULL) return -1;
*/
if(_beginthreadex(NULL, 0, RecvThrd, NULL, 0, NULL)==0)
{
printf("create thread failed\n");
return -1;
}
執行緒
unsigned __stdcall RecvThrd(void *pvParam)
{
int iLastGetOk = 0;
for(;;)
{
STUMsgProperty2 oMsgPropery;
memset(&oMsgPropery, '\0', sizeof(STUMsgProperty2));
int iRecvPkgLen = 0;
char* psPkg = NULL;
int iRet = Mr2Receive1(g_pHandle, &psPkg, &iRecvPkgLen, &oMsgPropery, 1000);
if(iRet==0)
{
g_ltLastTimeRecv = time(NULL);
++g_iRecvCount;
if(g_iRecvCount%100==0)
{
printf("recv ok: PkgContent[%s]\n, pkgID[%s], src[%s.%s], dest[%s.%s], pkgLen[%d], CorrPkgID[%s], UserData1[%s], UserData2[%s] \n", psPkg, oMsgPropery.m_szPkgID, oMsgPropery.m_szSourceUserID, oMsgPropery.m_szSourceAppID, oMsgPropery.m_szDestUserID, oMsgPropery.m_szDestAppID, iRecvPkgLen, oMsgPropery.m_szCorrPkgID, oMsgPropery.m_szUserData1, oMsgPropery.m_szUserData2);
printf("client recv count[%d]\n", g_iRecvCount);
}
#ifndef MR_CLIENT
STUMsgProperty2 oMsgProperySend;
memset(&oMsgProperySend, '\0', sizeof(STUMsgProperty2));
strcpy(oMsgProperySend.m_szDestUserID, oMsgPropery.m_szSourceUserID);
strcpy(oMsgProperySend.m_szDestAppID, oMsgPropery.m_szSourceAppID);
strcpy(oMsgProperySend.m_szCorrPkgID, oMsgPropery.m_szPkgID);
strcpy(oMsgProperySend.m_szUserData1, oMsgPropery.m_szUserData1);
strcpy(oMsgProperySend.m_szUserData2, oMsgPropery.m_szUserData2);
oMsgProperySend.m_ucFlag = 0;
int iRet = Mr2Send(g_pHandle, psPkg, iRecvPkgLen, &oMsgProperySend, 2000);
#endif
Mr2Receive1_FreeBuf(psPkg);
}
else
{
MySleep(500);
}
}
return 0;
}
uj5u.com熱心網友回復:
這是怎么回事?1. 介面檔案定義(delph宣告是根據這個來的):
void* _stdcall Mr2Init(const char* psAppID, const char* psPasswd, int (*OnRe ceive 2)(const char* psPkg, int iPkgLe n, const STUMsgProperty 2* pMsgPropery , void* pvUserData), const STUConnInfo 2* pArrC onnInfo , int iArrConnInfoCount , void* pvUserData);
另外你編譯一下他的C++ DEMO,看看能不能通過?我估計是不行的,因為函式宣告和實際呼叫的引數個數都不一樣嘛。
uj5u.com熱心網友回復:
我問過對方,int (*OnReceive 2)(const char* psPkg, int iPkgLen, const STUMsgProperty 2* pMsgPropery , void* pvUserData)是一個回呼函式指標,可以不用它,所以直接給了個nil值。
C++我沒環境……看能不能想辦法試試。
uj5u.com熱心網友回復:
那到底是6個引數還是5個?你分別試一下吧。uj5u.com熱心網友回復:
可以宣告成var ppsPkg:PAnsichar或者ppsPkg : PPAnsiChar轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/63135.html
上一篇:C#資料結構順序表錯在哪里 求解
