Hi, I have a question about a dynamically loaded library I am using. I have called it SqlWrite, it is for connecting and writing to a Microsoft SQL server DB. I have a function in it that is defined as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
extern "C" {
__declspec(dllexport) RETCODE __cdecl SqlExecS(SQLHANDLESTR* h, LPCSTR Statement)
{
RETCODE RetCode;
std::string input = Statement;
std::wostringstream conv;
conv << input.c_str();
std::wstring wCmd(conv.str());
WCHAR* wCCmd = const_cast<WCHAR*>(wCmd.c_str());
_setmode(_fileno(stdout), _O_WTEXT); // MSVC's special needs
std::wcout << "exec " << wCCmd;
RetCode = SQLExecDirect(h->hStmt,wCCmd, SQL_NTS);
std::wcout << " retcode " << RetCode << std::endl;
std::wcout << std::endl << "RETURNING FROM EXECSP NOW!!! " << std::endl;
return RetCode;
}
}
|
I then load it in another MSVC project as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
#ifdef WIN32// C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Debug\\GetPageSource.dll
#pragma message("WIN32 is defined")
#ifdef _DEBUG
SetErrorMode(0);
HINSTANCE hGetProcIDDLLGSP = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Debug\\GetPageSource.dll");
HINSTANCE hGetProcIDDLLREGEX = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\regex\\Debug\\regex.dll");
HINSTANCE hGetProcIDDLLSQLWRITE = LoadLibrary(L"C:\\Users\\a\\Documents\\visual studio 2012\\Projects\\SQLWrite\\Debug\\SQLWrite.dll");
#else
#ifdef NDEBUG
SetErrorMode(0);
HINSTANCE hGetProcIDDLLGSP = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Release\\GetPageSource.dll");
HINSTANCE hGetProcIDDLLREGEX = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\regex\\Release\\regex.dll");
HINSTANCE hGetProcIDDLLSQLWRITE = LoadLibrary(L"C:\\Users\\a\\Documents\\visual studio 2012\\Projects\\SQLWrite\\Release\\SQLWrite.dll");
#endif
#endif
#endif
#endif
|
. then I prototype it as:
1 2 3 4 5 6 7 8 9 10
|
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLLSQLWRITE),"SqlExecS");
std::cout << GetLastError() << std::endl;
/*
Define the Function in the DLL for reuse. This is just prototyping the dll's function.
*/
typedef RETCODE (__cdecl * pICFUNCSqlExecS)(SQLHANDLESTR* h, LPCSTR Statement);
pICFUNCSqlExecS SqlExecSP;
SqlExecSP = pICFUNCSqlExecS(lpfnGetProcessID);
|
And, finally, I use it as, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
SQLHANDLESTR * h = SqlConnectDBP();
if(h)
{
std::string comGP = std::string("SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = '");
comGP.append(plaDa->at(i).plName);
comGP.append("' AND FirstName = '");
comGP.append(plaDa->at(i).pfName);
comGP.append("'");
LPCSTR Statement = comGP.c_str();
SqlExecSP(h,Statement);
}
|
As you can see, inside the prototyped function "SqlExecSP", I cout (or, rather, wcout for wide characters) the sql statement i am running, and the return code of the sql statement. a sql return code of "0" is equivalent to "SQL_SUCCESS". Then, I cout " got player again " after executon of SqlExecSP alias SqlExecS.
This usually works, and gives me following sample output:
1 2 3 4
|
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0
RETURNING FROM EXECSP NOW!!!
got player again
|
However, sometimes, the program, for some reason that I have no idea why, crashes somewhere between outputting "RETURNING FROM EXECSP NOW!!!" and outputting " got player again ", i.e. the output is then:
1 2 3
|
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0
RETURNING FROM EXECSP NOW!!!
|
As you can see, it doesn't output the next line " got player again ", because it somehow crashes in between.
However,t he only line that should be executed between this, as far as I can understand, is the actual return of the DLL function SqlExecS, prototyped as SqlExecSP in my calling code, i.e. the only line that should be executed in between is:
return RetCode;
However, somehow, this fails, even though RetCode is "0", as I can see at the end of the output
|
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0
|
Now, I have no idea why sometimes this crashes, and sometimes this works. I.e, I can sometimes call this function x times, and it doesnt fail, outputting " got player again " right after the calls, and sometimes, it fails somewhere in between, at call x, y, or z, i.e. sometimes i can execute it ten times successfully and sometimes i can't, even though the return code is still 0, and it just fails somewhere in between, and I have no idea why. I am not sure if it has to do with the call being a call to a dynamically loaded DLL function, but I can't see where else the error is.
Does anyone have ANY idea why this can be failing, and at different, seemingly random times?
Thanks for any input and help!!! :)
hansaaa :)