Dynamically Load a Function from a Dll

Dynamically load a function from a DLL

LoadLibrary does not do what you think it does. It loads the DLL into the memory of the current process, but it does not magically import functions defined in it! This wouldn't be possible, as function calls are resolved by the linker at compile time while LoadLibrary is called at runtime (remember that C++ is a statically typed language).

You need a separate WinAPI function to get the address of dynamically loaded functions: GetProcAddress.

Example

#include <windows.h>
#include <iostream>

/* Define a function pointer for our imported
* function.
* This reads as "introduce the new type f_funci as the type:
* pointer to a function returning an int and
* taking no arguments.
*
* Make sure to use matching calling convention (__cdecl, __stdcall, ...)
* with the exported function. __stdcall is the convention used by the WinAPI
*/
typedef int (__stdcall *f_funci)();

int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop\\test.dll");

if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}

// resolve function address here
f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "funci");
if (!funci) {
std::cout << "could not locate the function" << std::endl;
return EXIT_FAILURE;
}

std::cout << "funci() returned " << funci() << std::endl;

return EXIT_SUCCESS;
}

Also, you should export your function from the DLL correctly. This can be done like this:

int __declspec(dllexport) __stdcall funci() {
// ...
}

As Lundin notes, it's good practice to free the handle to the library if you don't need them it longer. This will cause it to get unloaded if no other process still holds a handle to the same DLL.

C++ Dynamically load arbitrary function from DLL into std::function

Use the WinAPI functions provided in windows.h (descriptions taken from MSDN Dev Center).

  • LoadLibrary - Loads the specified module into the address space of the calling process. Returns a handle to the module.
  • GetProcAddress - Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL). Returns the address of the exported function or variable.

Use this function to load a specific function and return a std::function object:

// main.cc

#include <iostream>
#include <string>
#include <functional>
#include <windows.h>

template <typename T>
std::function<T> loadDllFunc(const std::string& dllName, const std::string& funcName) {
// Load DLL.
HINSTANCE hGetProcIDDLL = LoadLibrary(dllName.c_str());

// Check if DLL is loaded.
if (hGetProcIDDLL == NULL) {
std::cerr << "Could not load DLL \"" << dllName << "\"" << std::endl;
exit(EXIT_FAILURE);
}

// Locate function in DLL.
FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL, funcName.c_str());

// Check if function was located.
if (!lpfnGetProcessID) {
std::cerr << "Could not locate the function \"" << funcName << "\" in DLL\"" << dllName << "\"" << std::endl;
exit(EXIT_FAILURE);
}

// Create function object from function pointer.
std::function<T> func(reinterpret_cast<__stdcall T*>(lpfnGetProcessID));

return func;
}

The DLL source should be written like this:

// test.cc (test.dll)
#include <iostream>

// Declare function prototypes with "extern C" to prevent name mangling.
// Declare functions using __declspec(dllexport) to signify the intent to export.
extern "C" {
__declspec(dllexport) int __stdcall plusFive(int);
__declspec(dllexport) void __stdcall printHello();
}

int plusFive(int value) {
return value + 5;
}

void printHello() {
std::cout << "Hello!" << std::endl;
}

And then use loadDllFunc like this:

// main.cc

int main() {
auto func1 = loadDllFunc<int(int)>("test.dll", "plusFive");
auto func2 = loadDllFunc<void()>("test.dll", "printHello");

std::cout << "Result of func1: " << func1(1) << std::endl;
func2();
}

Output:

Result of func1: 6
Hello!

As a sidenote the DLL can be compiled using GCC (4.7.2) like this:

g++ -shared -o test.dll test.cc -std=c++11

Edit:

I'm not sure that the cast in loadDllFunc gives the correct type:

std::function<T> func(reinterpret_cast<__stdcall T*>(lpfnGetProcessID));

It seems to cast it to __stdcall int (*)(int) when it should be int (__stdcall *)(int).

Here is another way to implement loadDllFunc using an auxiliary parser class. This solution will correctly cast the function pointer to int (__stdcall *)(int).

template <typename T>
struct TypeParser {};

template <typename Ret, typename... Args>
struct TypeParser<Ret(Args...)> {
static std::function<Ret(Args...)> createFunction(const FARPROC lpfnGetProcessID) {
return std::function<Ret(Args...)>(reinterpret_cast<Ret (__stdcall *)(Args...)>(lpfnGetProcessID));
}
};

template <typename T>
std::function<T> loadDllFunc(const std::string& dllName, const std::string& funcName) {
// Load DLL.
HINSTANCE hGetProcIDDLL = LoadLibrary(dllName.c_str());

// Check if DLL is loaded.
if (hGetProcIDDLL == NULL) {
std::cerr << "Could not load DLL \"" << dllName << "\"" << std::endl;
exit(EXIT_FAILURE);
}

// Locate function in DLL.
FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL, funcName.c_str());

// Check if function was located.
if (!lpfnGetProcessID) {
std::cerr << "Could not locate the function \"" << funcName << "\" in DLL\"" << dllName << "\"" << std::endl;
exit(EXIT_FAILURE);
}

// Create function object from function pointer.
return TypeParser<T>::createFunction(lpfnGetProcessID);
}

Is there a better way to load a dll in C++?

After building your .dll get the .lib file nearby and link your test application with it. Use functions as they are declared in .h

There's a minor change you need to do in your header file:

#ifdef EXPORTS_API
#define MY_API_EXPORT __declspec (dllexport)
#else
#define MY_API_EXPORT __declspec (dllimport)
#endif

extern "C" {
int MY_API_EXPORT Factorial(int n);

// do the same for other functions
}

This way, when building your dll you define EXPORTS_API in your project settings and functions get exported, in the client application, no need to define anything.

How to dynamically load every needed function

The function in your example (printf) is not a Windows API function, rather it is a function defined in the C standard. Therefore it should be more readily available. However this re-enforces the point that if you don't have any of the either standard or Windows API functions available that makes for a lot of dlls to know about. I don't know of a single place that defines them all in one source file, but you can load your functions on a case by case basis using a resource like www.pinvoke.net which lets you type in a function name and retrieve the name of the dll to load (as well as the C# method signature but you don't need that, you already know the C signature).

C++: Dynamically loading classes from dlls

Easiest way to do this, IMHO, is to have a simple C function that returns a pointer to an interface described elsewhere. Then your app, can call all of the functions of that interface, without actually knowing what class it is using.

Edit: Here's a simple example.

In your main app code, you create a header for the interface:

class IModule
{
public:
virtual ~IModule(); // <= important!
virtual void doStuff() = 0;
};

Main app is coded to use the interface above, without any details on the actual implementation of the interface.

class ActualModule: public IModule
{
/* implementation */
};

Now, the modules - the DLL's have the actual implementations of that interface, and those classes don't even have to be exported - __declspec (dllexport) isn't needed. The only requirement for the modules is to export a single function, that would create and return an implementation of the interface:

__declspec (dllexport) IModule* CreateModule()
{
// call the constructor of the actual implementation
IModule * module = new ActualModule();
// return the created function
return module;
}

note: error checking left out - you'd usually want to check, if new returned the correct pointer and you should protect yourself from the exceptions that might be thrown in the constructor of the ActualModule class.

Then, in your main app, all you need is to simply load the module (LoadLibrary function) and find the function CreateModule (GetProcAddr function). Then, you use the class through the interface.

Edit 2: your RefCount (base class of the interface), can be implemented in (and exported from) the main app. Then all your module would need to link to the lib file of the main app (yes! EXE files can have LIB files just like DLL files!) And that should be enough.

How to dynamically call a function in a shared library?

First, your library function is called "foo3", but you're trying to load the symbol "foo".

Second, the library function's symbol may not match it's name due to mangling. You need to tell the compiler not to do that with the #[no_mangle] attribute:

#[no_mangle]
pub extern "C" fn foo(i: i32) -> i32 {
i
}

Third, this is mostly a stylistic choice, but I'd specify the ABI extern "C" when defining your symbol. Even though extern with no epecified ABI uses the "C" ABI, I've found it better to be explicit.

use libloading::{Library, Symbol};

fn main() {
unsafe {
let lib = Library::new("externtest.dll").unwrap();
let foo = lib
.get::<Symbol<extern "C" fn(i32) -> i32>>(b"foo")
.unwrap();

println!("{}", foo(1));
}
}

The above should work without issue.

C++ how to dynamically load a 3rd party DLL file

A dotNET = (Mircosoft) .NET Framework is not the same as a "normal" dll, you can't use GetProcAddress and LoadLibrary with .NET dlls

.Net Dlls are normally packed classes, by dragging the dll into your workspace you just import the dlls scope, see for your self in the object browser

to load a .net dll (Assembly) during runtime, for example for a plugin, look here http://support.microsoft.com/kb/837908



Related Topics



Leave a reply



Submit