I am in DLL Hell.. :(
-
Ok.. I dug out one of my old VC++ books Inside Visual C++ Version 4. I read the section on dlls after post many questions here and I still can't seem to get a pointer to my function. Following is the code I am using if anyone has any ideas it would be appreciated. Thanks, -Eric
Created this dll using the dllWizard as a shared MFC regular dll. This is the only exported function in the dll. __declspec(dllexport) CString SndMessage(CString strInMessage) { CString strOutMessage = _T("Inside TestDll.dll->SndMessage() "); strOutMessage += strInMessage; return strOutMessage; } //This is the relevant code from the Dialog application to test it. This is in the Dialog header file as public. typedef CString (SNDMESSAGE)(CString); HINSTANCE hDllHandle; SNDMESSAGE *fpFunction; Inside my OnInitdialog(). // TODO: Add extra initialization here hDllHandle = ::LoadLibrary(_T("TestDll.dll")); if(hDllHandle == NULL) MessageBox(_T("Error loading TestDll.dll")); else { fpFunction = (SNDMESSAGE *)::GetProcAddress((HMODULE)hDllHandle, "SndMessage"); if(fpFunction == NULL) { MessageBox(_T("Error obtaining address of SndMessage() in TestDll.dll")); PostMessage(WM_QUIT); } } void CTestingDllDlg::OnButtonTest() { // TODO: Add your control notification handler code here UpdateData(TRUE); m_strOutText = (*fpFunction)(m_strInText); UpdateData(FALSE); }
-
Ok.. I dug out one of my old VC++ books Inside Visual C++ Version 4. I read the section on dlls after post many questions here and I still can't seem to get a pointer to my function. Following is the code I am using if anyone has any ideas it would be appreciated. Thanks, -Eric
Created this dll using the dllWizard as a shared MFC regular dll. This is the only exported function in the dll. __declspec(dllexport) CString SndMessage(CString strInMessage) { CString strOutMessage = _T("Inside TestDll.dll->SndMessage() "); strOutMessage += strInMessage; return strOutMessage; } //This is the relevant code from the Dialog application to test it. This is in the Dialog header file as public. typedef CString (SNDMESSAGE)(CString); HINSTANCE hDllHandle; SNDMESSAGE *fpFunction; Inside my OnInitdialog(). // TODO: Add extra initialization here hDllHandle = ::LoadLibrary(_T("TestDll.dll")); if(hDllHandle == NULL) MessageBox(_T("Error loading TestDll.dll")); else { fpFunction = (SNDMESSAGE *)::GetProcAddress((HMODULE)hDllHandle, "SndMessage"); if(fpFunction == NULL) { MessageBox(_T("Error obtaining address of SndMessage() in TestDll.dll")); PostMessage(WM_QUIT); } } void CTestingDllDlg::OnButtonTest() { // TODO: Add your control notification handler code here UpdateData(TRUE); m_strOutText = (*fpFunction)(m_strInText); UpdateData(FALSE); }
The problem is you are exporting a C++ function and its name to the outside world is not SndMessage. C++ mangles the name of functions so that the arguments types are included. If you have successfully built your DLL you can find out exactly what the exported name is by typing "dumpbin /EXPORTS TestDll.dll" Dumpbin is one of the VC++ tools. One work around is to export a straight C function that exports a pointer to the string that is passed via a LONG and you cast it to a string pointer when you use it. This can be wrapped in a local C++ function so don't see the messy details. Note - in your current implementation, I believe that strOutMesage will be destroyed when SndMessage returns since it is then out of scope. The Ten Commandments For C Programmers
-
The problem is you are exporting a C++ function and its name to the outside world is not SndMessage. C++ mangles the name of functions so that the arguments types are included. If you have successfully built your DLL you can find out exactly what the exported name is by typing "dumpbin /EXPORTS TestDll.dll" Dumpbin is one of the VC++ tools. One work around is to export a straight C function that exports a pointer to the string that is passed via a LONG and you cast it to a string pointer when you use it. This can be wrapped in a local C++ function so don't see the messy details. Note - in your current implementation, I believe that strOutMesage will be destroyed when SndMessage returns since it is then out of scope. The Ten Commandments For C Programmers
Rick York wrote: The problem is you are exporting a C++ function and its name to the outside world is not SndMessage. C++ mangles the name of functions so that the arguments types are included. If you have successfully built your DLL you can find out exactly what the exported name is by typing "dumpbin /EXPORTS TestDll.dll" Dumpbin is one of the VC++ tools. One work around is to export a straight C function that exports a pointer to the string that is passed via a LONG and you cast it to a string pointer when you use it. This can be wrapped in a local C++ function so don't see the messy details. When I run Dumpbin this is what I get: Dump of file TestDll.dll File Type: DLL Section contains the following exports for TestDll.dll 0 characteristics 3E1E3F7D time date stamp Thu Jan 09 22:35:25 2003 0.00 version 1 ordinal base 0 number of functions 0 number of names ordinal hint RVA name Summary F000 .data 5000 .idata 11000 .rdata C000 .reloc 4000 .rsrc 10F000 .text Rick, any chance you can explain the second part of that to me? Thanks, -Eric
-
Ok.. I dug out one of my old VC++ books Inside Visual C++ Version 4. I read the section on dlls after post many questions here and I still can't seem to get a pointer to my function. Following is the code I am using if anyone has any ideas it would be appreciated. Thanks, -Eric
Created this dll using the dllWizard as a shared MFC regular dll. This is the only exported function in the dll. __declspec(dllexport) CString SndMessage(CString strInMessage) { CString strOutMessage = _T("Inside TestDll.dll->SndMessage() "); strOutMessage += strInMessage; return strOutMessage; } //This is the relevant code from the Dialog application to test it. This is in the Dialog header file as public. typedef CString (SNDMESSAGE)(CString); HINSTANCE hDllHandle; SNDMESSAGE *fpFunction; Inside my OnInitdialog(). // TODO: Add extra initialization here hDllHandle = ::LoadLibrary(_T("TestDll.dll")); if(hDllHandle == NULL) MessageBox(_T("Error loading TestDll.dll")); else { fpFunction = (SNDMESSAGE *)::GetProcAddress((HMODULE)hDllHandle, "SndMessage"); if(fpFunction == NULL) { MessageBox(_T("Error obtaining address of SndMessage() in TestDll.dll")); PostMessage(WM_QUIT); } } void CTestingDllDlg::OnButtonTest() { // TODO: Add your control notification handler code here UpdateData(TRUE); m_strOutText = (*fpFunction)(m_strInText); UpdateData(FALSE); }
It sounds to me like you need to use a .def file. I'm not positive, but if it's the GetProcAddress that's failing, this is probably the case. Chris Richardson Programmers find all sorts of ingenious ways to screw ourselves over. - Tim Smith
-
Ok.. I dug out one of my old VC++ books Inside Visual C++ Version 4. I read the section on dlls after post many questions here and I still can't seem to get a pointer to my function. Following is the code I am using if anyone has any ideas it would be appreciated. Thanks, -Eric
Created this dll using the dllWizard as a shared MFC regular dll. This is the only exported function in the dll. __declspec(dllexport) CString SndMessage(CString strInMessage) { CString strOutMessage = _T("Inside TestDll.dll->SndMessage() "); strOutMessage += strInMessage; return strOutMessage; } //This is the relevant code from the Dialog application to test it. This is in the Dialog header file as public. typedef CString (SNDMESSAGE)(CString); HINSTANCE hDllHandle; SNDMESSAGE *fpFunction; Inside my OnInitdialog(). // TODO: Add extra initialization here hDllHandle = ::LoadLibrary(_T("TestDll.dll")); if(hDllHandle == NULL) MessageBox(_T("Error loading TestDll.dll")); else { fpFunction = (SNDMESSAGE *)::GetProcAddress((HMODULE)hDllHandle, "SndMessage"); if(fpFunction == NULL) { MessageBox(_T("Error obtaining address of SndMessage() in TestDll.dll")); PostMessage(WM_QUIT); } } void CTestingDllDlg::OnButtonTest() { // TODO: Add your control notification handler code here UpdateData(TRUE); m_strOutText = (*fpFunction)(m_strInText); UpdateData(FALSE); }
Change:
__declspec(dllexport) CString SndMessage(CString strInMessage)
to:
extern "C" __declspec(dllexport) CString SndMessage(CString strInMessage)
Rickard Andersson@Suza Computing C# and C++ programmer from SWEDEN! UIN: 50302279 E-Mail: nikado@pc.nu Speciality: I love C#, ASP.NET and C++!
-
Change:
__declspec(dllexport) CString SndMessage(CString strInMessage)
to:
extern "C" __declspec(dllexport) CString SndMessage(CString strInMessage)
Rickard Andersson@Suza Computing C# and C++ programmer from SWEDEN! UIN: 50302279 E-Mail: nikado@pc.nu Speciality: I love C#, ASP.NET and C++!
I think this would help but I think the CString created will be gone once it is out of scope. I think the CString needs to be new-ed and passed as a pointer. The Ten Commandments For C Programmers