Jump to content
  • Advertisement
Sign in to follow this  
lostincpp

[Resolved] Can't Load Functions from a DLL

This topic is 3924 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've written a simple DLL using Borland Developer Studio 2006 C++ Builder. I've also written an application that does nothing other than a dynamic load of the DLL and attempt to access a single function. Everything compiles without errors or warnings, the DLL appears to load properly, but I cannot load the function. I have looked in books and read what I could find on the internet pertaining to creating and using DLLs dynamically and everything seems to be fine. Could some of you DLL experts take a look at the code below and tell me why the function itself cannot be accessed? The DLL header file:
/* dllproj1.h */
extern "C" char* __declspec(dllexport) dllString1(void);



The DLL source CPP:
/* dllproj1.cpp */
#include <windows.h>
#include <dllproj1.h>

#pragma argsused

int WINAPI DllEntryPoint1(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
	return 1;
}
char* dllString1(void){
	return "This is from DLL 1";
	}



The applicable portion of the application header:
...
private:	// User declarations
	HMODULE hDll;
	typedef char* (__declspec(dllimport) *LPFNC_DLLSTRING) (void);
	LPFNC_DLLSTRING lpfnc_dllstring;
...



The applicable portion of the application source .CPP :
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    char* szBuffer = "Operation aborted";
    //Load the specific library
    hDll = LoadLibrary("..\\..\\dlltest\\debug_build\\dllproj1.dll");
    if(!hDll){
	   Memo1->Lines->Add("Dll not loaded");
	   return;
	   }else{
		   Memo1->Lines->Add("Dll loaded");
		   }
   
    lpfnc_dllstring = (LPFNC_DLLSTRING)(GetProcAddress(hDll, "_dllString1"));
    if(lpfnc_dllstring){
	   Memo1->Lines->Add("Function found");

	   }else{
		   Memo1->Lines->Add("Function NOT found");
		   FreeLibrary(hDll);
		   return;
	   }
	//Call the function from the DLL

	szBuffer = lpfnc_dllstring();

	Memo1->Text = szBuffer;
}



I've actually tried many different variations on the code above but this is the latest version. The function pointer lpfnc_dllstring always returns "Function NOT found". I've never been able find the function from the DLL. Any suggestions? Thanks in advance. [Edited by - lostincpp on September 27, 2007 4:48:46 PM]

Share this post


Link to post
Share on other sites
Advertisement
Tried that as well. Changed it when I found a note in the Borland Help that said C++ Builder automatically puts an underscore in front of the name when it compiles the DLL. But I tried it again at your suggestion and have the same results.

That was my original suspicion, that some type of name-mangling was going on during the compile process. Know of any way that I can check what the actual compiled name would be?

Share this post


Link to post
Share on other sites
Are you using a DEF file? There is a common misconception among C++ programmers that the __declspec(dllexport) qualifier is a substitute for a library definition file, but this isn't the case. Unless you provide such a set of definitions, the compiler is free to decorate your function names to make things easier for the linker. By 'decorate', I (along with everyone else) mean appending various symbols to the name to describe its stack footprint and calling convention (e.g. msvcr70.dll's exception() ends up looking like ??_Gexception@@UAEPAXI@Z).

This may, or may not be your problem. You can find out for sure by viewing the DLL in a PE editor (or dumpbin, or the MS Dependency Walker). If this turns out to be the case, you have two options. Either use the decorated names with LoadLibrary, which is a bad idea for several reasons, or recompile the DLL with an appropriate definition file.

Admiral

Share this post


Link to post
Share on other sites
I used Dependency Walker and found out that the function was not even being exported. So, I started the project over and kept the DLL files to a minimum.

Here's the final DLL source file. I eliminated the header file. Nothing was changed in the application file other than the name of the actual function as it was finally exported.


#include <windows.h>
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
extern "C"{
char* __declspec(dllexport) dllString1(void)
{
return "From DLL 1";
}

} // end of extern "C" block



For anyone who doesn't know and might be reading this for a similar problem:

__declspec(dllexport) should appear just before the function name that you intend to export.

extern "C" prevents your exported function names from being C++ mangled so that the exported name will be the actual name of your function, except where your compiler might be adding characters.

If you are using a Borland compiler, an underscore is inserted prior to the function name. You can turn that option off so that the underscore isn't generated.

I did not need a .DEF file. I'm not certain if its because I was using dynamic linking or because I was using __declspec(dllexport). Information I could obtain from the internet wasn't clear about when to use .DEF and when not.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!