Okay so I'm coming dangerously close to a repost here but my situation is a little bit different than the numerous other posters about this function. I am interfacing with a DLL that was written way back in the day and all I have is the file. I don't have a .lib file so I'm using the LoadLibrary and GetProcessAddress functions. I followed the tutorial on the MSDN website to get the basic structure. the DLL is located in the project folder. it compiles. at run time, I am getting a numerical value for "hinstLib" so I'm assuming the DLL was found. I am getting a null value for "ProcAdd" variable. Other posters had there issues resolved by putting extern C in the DLL functions but I don't really have that option. not to mention, to my knowledge this DLL was written in plain C. I do have an interface document and am quite sure I have the function name correct (replaced with a generic example for these purposes). I honestly didn't run anything past the ProcAdd assignment because it came out NULL. Any thoughts as to why this is giving me a 0 value for the function assignment would be great appreciated. Note: unfortunately due to various reasons I can't upload the DLL.
#include <iostream>
#include "stdafx.h"
#include "Windows.h"
#include <stdio.h>
typedef int(__cdecl *MYPROC)(LPWSTR);
using namespace std;
int main()
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
hinstLib = LoadLibrary(TEXT("dllName.dll"));
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "funcName");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
//(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
Compilers usually mangle function names, then a function named funcName may appear inside the DLL with a name funcName#16 , for example... It depends on calling convention and are important for a function to be called properly. For __cdecl calling convention you probably need _funcName :-) .
Related
This question already has answers here:
Cast to LPCWSTR?
(4 answers)
Closed 3 years ago.
I'm trying to load a DLL into C++ but was getting error code 126, which I think means the DLL couldn't be found. After some poking around I changed LoadLibrary to LoadLibraryA and suddendly it worked. However, I am at a complete loss as to why. I realise that I haven't provided the dll for this code to be runable but would be greatful if somebody could provide an explaination as to why this is happening? And prehaps an example of how to get LoadLibary working.
Broken version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
Error loading dll: 126/nHit any key to continue
to console
Working version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibraryA("libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
version is: 1.3.4
The problem with your LoadLibrary((LPCWSTR)"libsbnw.dll") call is that your build environment converts that to a LoadLibraryW call, but the way you are trying to pass a wide-character string is wrong.
As you have it, you are simply casting a const char* pointer to a const wchar_t* pointer, which won't work (for example, it will interpret the initial "li" characters as a single 16-bit character).
What you need to do is specify the string literal as a wide character constant, using the L prefix:
HINSTANCE hLib = LoadLibrary(L"libsbnw.dll");
Or, alternatively, using the TEXT() macro (which will boil down to the same, when using the UNICODE build environment):
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
Feel free to ask for further explanation and/or clarification.
Ordinarily the compiler will try to point out when you're making a mistake. But in this case you've told it not to by adding an explicit cast to the string.
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
//^^^^^^^^^
I'm assuming you've built your app with Unicode enabled, which defines a macro converting LoadLibrary to LoadLibraryW. The parameter must be a wide-character string.
HINSTANCE hLib = LoadLibraryW(L"libsbnw.dll");
There's another macro you can use when you're not sure if the app will be compiled with Unicode or not, TEXT() or the shorter form _T(). Not recommended for modern code since needing to turn Unicode on or off hasn't been a problem in many years, just use Unicode always.
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
I want to write a very, very small program that parses the launch arguments and chooses one of several DLLs to "boot into."
I've already written an application that I'd like to "run" as a DLL by writing it as an application, then changing the Visual Studio project properties to build it as a DLL instead. I know I need to use LoadLibrary and GetProcAddress in concert to get the functionality I want, but I'm having trouble finding clear and comprehensive documentation on this, as a lot of the use cases aren't really of this nature. Also, I have to go this route based on the project and platform restrictions.
I found this page, which has some information, but it's not clear enough for me to adapt for my purposes.
Edit: Here's where I'm at right now.
I have a DLL project whose main function signature looks something like this:
__declspec(dllexport) int cdecl main(int argc, char *argv[])
I also have an application project whose attempt at loading the DLL and running the above function looks like this:
typedef int (CALLBACK* LPFNDLLFUNC1)(int, char *);
...
HMODULE dllHandle = NULL;
BOOL freeResult, runTimeLinkSuccess = FALSE;
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
if (args->IsEmpty())
{
dllHandle = LoadLibrary(L"TrueApplication.dll");
if (NULL != dllHandle)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(dllHandle, "main");
if (lpfnDllFunc1)
{
int retVal = lpfnDllFunc1(0, "1");
}
Currently, the LoadLibrary call works, but not GetProcAddress.
First of all, changing project type from executable to DLL is not enough to make a DLL. You also need to export some symbols to create your API. At least, you need to decorate the functions you are exporting with __declspec(dllexport). However, I recommend that you export C API, meaning extern "C" functions with C-compatible arguments. So, the functions you export should be prepended with extern "C" __declspec(dllexport).
Once you have done that, you can dynamically load your DLL like this:
const char* dllname = "myfile.dll";
h = LoadLibrary(dllname);
if( h == nullptr )
{
/*handle error*/
}
using myfunc_type = bool (*)(int x, double y); //example
auto myfunc = reinterpret_cast<myfunc_type>(GetProcAddress(h, "myfunc"));
//......
myfunc(x,y); //call the imported function
This solution takes more work than static loading with /delayload shown by Jerry Coffin, but it has an advantage: if a DLL is required but not found, you can give users your own error message instead of relying on the message coming from Windows (which is often unacceptable for non-tech people). You can also include API version verification with its own custom error message in the API.
Edit: the code sample will work if you change it like this
extern "C" __declspec(dllexport) int main(int argc, char *argv[]){...}
typedef int (* LPFNDLLFUNC1)(int, char **);
You do not need GetProcAddress (...) to do this, though that approach (Option #2) is simpler once you understand how the compiler generates symbol names.
Option #1
DllMain Spawns a Main Thread
Never do anything complicated inside of DllMain, you may deadlock your software.
DLLs have their own entry-point (and exit-point and thread attach-point ... it's a really busy function). Just calling LoadLibrary (...) on your DLL causes at minimum one call to DllMain (...) for process attach.
BOOL
APIENTRY
DllMain ( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
You can actually treat ul_reason_for_call == DLL_PROCESS_ATTACH as a mandate to execute DllMain as if it were your program's main function.
Now, by no means should you actually start a program loop here... anytime DllMain runs it holds a very important operating system lock (DLL Loader) and you need to release that by returning for normal program operation.
That means if you want to use DllMain as your program's entry-point, it needs to spawn a thread and your original main method must not return until that thread finishes...
Option #2
DLL Exports a main Function.
Be very mindful of calling convention, the compiler will rename the symbols for you and make locating functions in a DLL with GetProcAddress less than intuitive.
In your DLL, export main:
__declspec (dllexport)
int
__cdecl main (int argc, char *argv [])
{
printf ("foobar");
return 0;
}
In your program, import main from the DLL:
// Need a typedef for the function you are going to get from the DLL
typedef int (__cdecl *main_pfn)(int argc, char *argv[]);
int main (int argc, char *argv[])
{
HMODULE hModMyDLL = LoadLibraryA ("MyDll.dll");
if (hModMyDLL != 0) {
//
// The preceding underscore deals with automatic decorations
// the compiler added to the __cdecl function name.
//
// It is possible to do away with this completely if you use a .def
// file to assign export names and ordinals manually, but then you
// lose the ability to tell a function's calling convention by its
// name alone.
//
main_pfn MyMain = (main_pfn)
GetProcAddress (hModMyDLL, "_main");
// Call the main function in your DLL and return when it does
if (MyMain != nullptr)
return MyMain (argc, argv);
}
return -1;
}
Both approaches have their merits.
Spawning a thread from DllMain avoids knowing anything at all about how the DLL you want to load is is implemented, but it also requires you to design your main function never to return -- the DLL will call ExitProcess (...).
Exporting functions and later importing them by name allows you to avoid pussyfooting around the Windows DLL loaderlock. However, if you do not use a .def file to explicitly name the exported symbols, the compiler is going to add decorations such as _... (__cdecl) or ...#n (__stdcall) to the names and you have to learn these conventions to do anything useful with GetProcAddress.
You don't have to use LoadLibrary and GetProcAddress to invoke the functionality in the DLL.
More often, you'd create your DLLs, each with its own entry point. For the moment, let's assume you want to parse the command line, choose a DLL, and invoke its entry point without arguments. You end up with something like this:
void DLL_a();
void DLL_b();
void DLL_c();
int main(int argc, char **argv) {
// we'll assume DLL_a is the default:
if (argc < 2)
DLL_a();
// For now, we'll do a *really* trivial version of parsing the command line
// to choose the right DLL:
if (argv[1][0] == 'A')
DLL_a();
else if (argv[1]][0] == 'B')
DLL_b();
else if (argv[1][0] == 'C')
DLL_c();
else {
std::cerr << "Unrecognized argument\n";
return 1;
}
}
When you link your main, you'll specify the .lib corresponding to each DLL, and you'll probably want to specify the /delayload flag to the linker. This means a DLL won't be loaded until a function in the DLL is actually invoked. If, for example, you want to distribute a reduced-functionality version of your program that only includes DLL A, it'll still be able run (without DLL B or C present on the user's system) as long as no function from DLL B or C is ever called. If you don't specify /delayload, the loader will attempt to map all the DLLs to RAM as the program starts up, run their DllMain to initialize them for use, do the same recursively for all the DLLs they depend on, etc.
/delayload has one other advantage: it avoids mapping the other DLLs to addresses at all if they're never used. It sounds like any given invocation will only use one DLL, so that's probably a win in your case.
This is my exported function in dll1
extern"C" __declspec(dllexport) int FUN1(char* p){
return p[0];
}
I am calling this FUN1 from other project.Below is the code
#include
#include
using namespace std;
typedef int (*MYFUN1)(char*);
int main()
{
HMODULE hMod = LoadLibrary ("C:\\Users\\admin\\Documents\\Visual Studio 2010\\Projects\\CalledFun\\Debug\\CalledFun.exe");
if(hMod != NULL)
{
MYFUN1 pCtor = (MYFUN1) GetProcAddress (hMod, "FUN1");
int a = pCtor("calling a value") ;
cout<<a;
}
}
If I remove the extern "C" from dll1 then that function address is returning as NULL when calling GetProcAddress in dll2. Since both are written in c++ I thought name mangling will not effect this.I thought if we use c and c++ libraries combinely then only we need to mention extern "C" ,Can anyone help me to get out of this confusion
Thanks in advance
You need to disable name mangling because you are using Windows API like LoadLibrary to which you provide function name. Windows API an LoadLibrary in particular know nothing about your compiler name mangling, so you need to turn it off.
code:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
void calldll();
int main(int argc, char *argv[])
{
calldll();
system("PAUSE");
return EXIT_SUCCESS;
}
void calldll()
{
HINSTANCE LoadMe;
LoadMe = LoadLibrary("Trans_ATL.dll");
if(LoadMe!=0)
cout<<"loaded successfully\n";
else
cout<<"loading error\n";
/* get pointer to the functions in the dll*/
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
FARPROC function02 = GetProcAddress(LoadMe,"EnableEmphaticLAM_RAA");
FARPROC function03 = GetProcAddress(LoadMe,"SetText");
FARPROC function04 = GetProcAddress(LoadMe,"GetResult");
typedef void (__stdcall * pICFUNC01)(bool);
typedef void (__stdcall * pICFUNC02)(bool);
typedef bool (__stdcall * pICFUNC03)(string);
typedef string (__stdcall * pICFUNC04)(string);
pICFUNC01 EnableLastCharTashkeel_function;
EnableLastCharTashkeel_function = pICFUNC01(function01);
pICFUNC02 EnableEmphaticLAM_RAA_function;
EnableEmphaticLAM_RAA_function = pICFUNC02(function02);
pICFUNC03 SetText_function;
SetText_function = pICFUNC03(function03);
pICFUNC04 GetResult_function;
GetResult_function = pICFUNC04(function04);
EnableLastCharTashkeel_function(true);
EnableEmphaticLAM_RAA_function(true);
FreeLibrary(LoadMe);
}
in this code i call a dll it load successfully but when i try to use any function it compile without any errors but at the line
EnableLastCharTashkeel_function(true); (first call for a function)
it froozes and give me the following
Unhandled exception at 0x00000000 in test_trans_new.exe: 0xC0000005: Access violation reading location 0x00000000.
i guess that this becuse the function pointer point to NULL but i don't know how to fix it
i use visual c++ 2010
thanks in advance
thank you for all your replies which are realy helpfull but the problem still ocurrs but i approximately know the reason if i correct the problem is that the functions i try to access are of type COM so any idea about using this type
thanks in advance
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
That's a guaranteed NULL. Calling it does go kaboom, you didn't check if the function succeeded. The exported function is not named "EnableLastCharTashkeel". A more likely string is "?EnableLastCharTashkeel##YAX_N#Z". That's the name of the function after the C++ compiler mangled it, a trick to support overloaded functions.
You can declare the function extern "C", that suppresses name mangling and makes the function name "_EnableLastCharTashkeel". Note the leading underscore, used by the 32-bit compiler to mark that the function uses the __cdecl calling convention. To be sure, run Dumpbin.exe /exports on your DLL from the Visual Studio Command Prompt, it shows the exported names.
It's most likely 0 because the symbol you were trying to find in the DLL wasn't found, which would suggest that (a) it's either not there or (b) there might be a typo in the function name or (c) the function name might be mangled because it's being exported as a decorated name. This happens quite a lot in C++...
Unless the library exporting those four functions is under your control, use dumpbin /EXPORTS and have a look at the correct spelling of the symbols.
I have a basic solution file (.sln) where I was able to reproduce a problem I have been facing recently.
It contains 3 projects:
1.) MathTest.lib - containing methods that might cause a mathematical error, like acos(1.1).
2.) MathTestDll.dll - calls the methods from the above lib.
3.) UnitTest.exe - calls the exported method in the DLL that should cause the error.
What I'm trying to do is fairly simple:
The following code contains the _matherr() routine and should ideally link fine. The call to acos() with a value of 1.1 is invalid (invalid input) and should cause an error which should be handled by the implemented _matherr() handler. I hope I'm right about the behavior of _matherr(). Please let me know.
MathTest.lib
#include "MathTest.h"
#include <iostream>
#include <math.h>
int _matherr(_exception* _Except)
{
std::cout << _Except->name;
return -1;
}
void MathTest::ThrowMatherr(float par)
{
float result = acos(par);
std::cout << result;
}
This 'ThrowMatherr()' method will be called by the DLL as follows:
MathTestDll.dll
void MatherrCaller::CauseMatherr()
{
MathTest* mathtest = new MathTest();
mathtest->ThrowMatherr(1.1);
}
which is then exported as:
extern "C" __declspec(dllexport) void CallThisToCauseMatherr();
void CallThisToCauseMatherr()
{
MatherrCaller* caller = new MatherrCaller();
caller->CauseMatherr();
}
This exported method will be called by a simple test.
UnitTest.exe
#include <windows.h>
typedef void (*METHODTOCALL)();
int main()
{
HMODULE module = LoadLibrary((LPCSTR)"..\\Debug\\MatherrTestDll.dll");
if(module != NULL)
{
METHODTOCALL ProcAdd = (METHODTOCALL) GetProcAddress(module, (LPCSTR)"CallThisToCauseMatherr");
if (NULL != ProcAdd)
{
(ProcAdd)();
}
FreeLibrary(module);
}
return 0;
}
All methods get called fine. But the acos() method which has been passed invalid input never calls the _matherr() error handler. Please let me know how I can fix this.
I had to make the question detailed to get my point through. Please don't mind.
It is explicitly mentioned in the documentation for _matherr:
For special error handling, you can
provide a different definition of
_matherr. If you use the dynamically linked version of the C run-time
library (Msvcr90.dll), you can replace
the default _matherr routine in a
client executable with a user-defined
version. However, you cannot
replace the default _matherr routine
in a DLL client of Msvcr90.dll.
You'll need to put the override in the EXE module. Alter your unit test to accommodate this.