Dynamically load a function from a DLL - c++

I'm having a little look at .dll files, I understand their usage and I'm trying to understand how to use them.
I have created a .dll file that contains a function that returns an integer named funci()
using this code, I (think) I've imported the .dll file into the project(there's no complaints):
#include <windows.h>
#include <iostream>
int main() {
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop \\fgfdg\\dgdg\\test.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "cannot locate the .dll file" << std::endl;
} else {
std::cout << "it has been called" << std::endl;
return -1;
}
int a = funci();
return a;
}
# funci function
int funci() {
return 40;
}
However when I try to compile this .cpp file that I think has imported the .dll I have the following error:
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp||In function 'int main()':|
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp|16|error: 'funci' was not declared in this scope|
||=== Build finished: 1 errors, 0 warnings ===|
I know a .dll is different from a header file so I know I can't import a function like this but it's the best I could come up with to show that I've tried.
My question is, how can I use the hGetProcIDDLL pointer to access the function within the .dll.
I hope this question makes sense and I'm not barking up some wrong tree yet again.

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.

In addition to the already posted answer, I thought I should share a handy trick I use to load all the DLL functions into the program through function pointers, without writing a separate GetProcAddress call for each and every function. I also like to call the functions directly as attempted in the OP.
Start by defining a generic function pointer type:
typedef int (__stdcall* func_ptr_t)();
What types that are used aren't really important. Now create an array of that type, which corresponds to the amount of functions you have in the DLL:
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
In this array we can store the actual function pointers that point into the DLL memory space.
Next problem is that GetProcAddress expects the function names as strings. So create a similar array consisting of the function names in the DLL:
const char* DLL_FUNCTION_NAMES [DLL_FUNCTIONS_N] =
{
"dll_add",
"dll_subtract",
"dll_do_stuff",
...
};
Now we can easily call GetProcAddress() in a loop and store each function inside that array:
for(int i=0; i<DLL_FUNCTIONS_N; i++)
{
func_ptr[i] = GetProcAddress(hinst_mydll, DLL_FUNCTION_NAMES[i]);
if(func_ptr[i] == NULL)
{
// error handling, most likely you have to terminate the program here
}
}
If the loop was successful, the only problem we have now is calling the functions. The function pointer typedef from earlier isn't helpful, because each function will have its own signature. This can be solved by creating a struct with all the function types:
typedef struct
{
int (__stdcall* dll_add_ptr)(int, int);
int (__stdcall* dll_subtract_ptr)(int, int);
void (__stdcall* dll_do_stuff_ptr)(something);
...
} functions_struct;
And finally, to connect these to the array from before, create a union:
typedef union
{
functions_struct by_type;
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
} functions_union;
Now you can load all the functions from the DLL with the convenient loop, but call them through the by_type union member.
But of course, it is a bit burdensome to type out something like
functions.by_type.dll_add_ptr(1, 1); whenever you want to call a function.
As it turns out, this is the reason why I added the "ptr" postfix to the names: I wanted to keep them different from the actual function names. We can now smooth out the icky struct syntax and get the desired names, by using some macros:
#define dll_add (functions.by_type.dll_add_ptr)
#define dll_subtract (functions.by_type.dll_subtract_ptr)
#define dll_do_stuff (functions.by_type.dll_do_stuff_ptr)
And voilĂ , you can now use the function names, with the correct type and parameters, as if they were statically linked to your project:
int result = dll_add(1, 1);
Disclaimer: Strictly speaking, conversions between different function pointers are not defined by the C standard and not safe. So formally, what I'm doing here is undefined behavior. However, in the Windows world, function pointers are always of the same size no matter their type and the conversions between them are predictable on any version of Windows I've used.
Also, there might in theory be padding inserted in the union/struct, which would cause everything to fail. However, pointers happen to be of the same size as the alignment requirement in Windows. A static_assert to ensure that the struct/union has no padding might be in order still.

This is not exactly a hot topic, but I have a factory class that allows a dll to create an instance and return it as a DLL. It is what I came looking for but couldn't find exactly.
It is called like,
IHTTP_Server *server = SN::SN_Factory<IHTTP_Server>::CreateObject();
IHTTP_Server *server2 =
SN::SN_Factory<IHTTP_Server>::CreateObject(IHTTP_Server_special_entry);
where IHTTP_Server is the pure virtual interface for a class created either in another DLL, or the same one.
DEFINE_INTERFACE is used to give a class id an interface. Place inside interface;
An interface class looks like,
class IMyInterface
{
DEFINE_INTERFACE(IMyInterface);
public:
virtual ~IMyInterface() {};
virtual void MyMethod1() = 0;
...
};
The header file is like this
#if !defined(SN_FACTORY_H_INCLUDED)
#define SN_FACTORY_H_INCLUDED
#pragma once
The libraries are listed in this macro definition. One line per library/executable. It would be cool if we could call into another executable.
#define SN_APPLY_LIBRARIES(L, A) \
L(A, sn, "sn.dll") \
L(A, http_server_lib, "http_server_lib.dll") \
L(A, http_server, "")
Then for each dll/exe you define a macro and list its implementations. Def means that it is the default implementation for the interface. If it is not the default, you give a name for the interface used to identify it. Ie, special, and the name will be IHTTP_Server_special_entry.
#define SN_APPLY_ENTRYPOINTS_sn(M) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, def) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, special)
#define SN_APPLY_ENTRYPOINTS_http_server_lib(M) \
M(IHTTP_Server, HTTP::server::server, http_server_lib, def)
#define SN_APPLY_ENTRYPOINTS_http_server(M)
With the libraries all setup, the header file uses the macro definitions to define the needful.
#define APPLY_ENTRY(A, N, L) \
SN_APPLY_ENTRYPOINTS_##N(A)
#define DEFINE_INTERFACE(I) \
public: \
static const long Id = SN::I##_def_entry; \
private:
namespace SN
{
#define DEFINE_LIBRARY_ENUM(A, N, L) \
N##_library,
This creates an enum for the libraries.
enum LibraryValues
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_ENUM, "")
LastLibrary
};
#define DEFINE_ENTRY_ENUM(I, C, L, D) \
I##_##D##_entry,
This creates an enum for interface implementations.
enum EntryValues
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_ENUM)
LastEntry
};
long CallEntryPoint(long id, long interfaceId);
This defines the factory class. Not much to it here.
template <class I>
class SN_Factory
{
public:
SN_Factory()
{
}
static I *CreateObject(long id = I::Id )
{
return (I *)CallEntryPoint(id, I::Id);
}
};
}
#endif //SN_FACTORY_H_INCLUDED
Then the CPP is,
#include "sn_factory.h"
#include <windows.h>
Create the external entry point. You can check that it exists using depends.exe.
extern "C"
{
__declspec(dllexport) long entrypoint(long id)
{
#define CREATE_OBJECT(I, C, L, D) \
case SN::I##_##D##_entry: return (int) new C();
switch (id)
{
SN_APPLY_CURRENT_LIBRARY(APPLY_ENTRY, CREATE_OBJECT)
case -1:
default:
return 0;
}
}
}
The macros set up all the data needed.
namespace SN
{
bool loaded = false;
char * libraryPathArray[SN::LastLibrary];
#define DEFINE_LIBRARY_PATH(A, N, L) \
libraryPathArray[N##_library] = L;
static void LoadLibraryPaths()
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_PATH, "")
}
typedef long(*f_entrypoint)(long id);
f_entrypoint libraryFunctionArray[LastLibrary - 1];
void InitlibraryFunctionArray()
{
for (long j = 0; j < LastLibrary; j++)
{
libraryFunctionArray[j] = 0;
}
#define DEFAULT_LIBRARY_ENTRY(A, N, L) \
libraryFunctionArray[N##_library] = &entrypoint;
SN_APPLY_CURRENT_LIBRARY(DEFAULT_LIBRARY_ENTRY, "")
}
enum SN::LibraryValues libraryForEntryPointArray[SN::LastEntry];
#define DEFINE_ENTRY_POINT_LIBRARY(I, C, L, D) \
libraryForEntryPointArray[I##_##D##_entry] = L##_library;
void LoadLibraryForEntryPointArray()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_POINT_LIBRARY)
}
enum SN::EntryValues defaultEntryArray[SN::LastEntry];
#define DEFINE_ENTRY_DEFAULT(I, C, L, D) \
defaultEntryArray[I##_##D##_entry] = I##_def_entry;
void LoadDefaultEntries()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_DEFAULT)
}
void Initialize()
{
if (!loaded)
{
loaded = true;
LoadLibraryPaths();
InitlibraryFunctionArray();
LoadLibraryForEntryPointArray();
LoadDefaultEntries();
}
}
long CallEntryPoint(long id, long interfaceId)
{
Initialize();
// assert(defaultEntryArray[id] == interfaceId, "Request to create an object for the wrong interface.")
enum SN::LibraryValues l = libraryForEntryPointArray[id];
f_entrypoint f = libraryFunctionArray[l];
if (!f)
{
HINSTANCE hGetProcIDDLL = LoadLibraryA(libraryPathArray[l]);
if (!hGetProcIDDLL) {
return NULL;
}
// resolve function address here
f = (f_entrypoint)GetProcAddress(hGetProcIDDLL, "entrypoint");
if (!f) {
return NULL;
}
libraryFunctionArray[l] = f;
}
return f(id);
}
}
Each library includes this "cpp" with a stub cpp for each library/executable. Any specific compiled header stuff.
#include "sn_pch.h"
Setup this library.
#define SN_APPLY_CURRENT_LIBRARY(L, A) \
L(A, sn, "sn.dll")
An include for the main cpp. I guess this cpp could be a .h. But there are different ways you could do this. This approach worked for me.
#include "../inc/sn_factory.cpp"

Related

Call a function in C++ by its address without knowing the return type

I want to call a C function from a C++ dll by its address.
I know how to do it where the return type is known from this separate question: Calling a function through its address in memory in c / c++.
However, if I do not know the return type, what can I do? I've tried "typedef auto", but it seems you cannot use auto like that.
If the returning type is really unknown or it doesn't matter, you can use void in your function definition, or if it is any pointer you can use void *, but if the function is in a C coded DLL, and you'll use it in a C++ code, then you can utilize and share almost every type defined in your C code, because C++ it's a superset of C.
That said, I prepared a small example with a structure called PyObject shared in C and C++ codes.
To do this, is better creating a header with the shared types/definitions:
#ifndef PYOBJECT_DLL_H
#define PYOBJECT_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
// Common structure definition
typedef struct PyObject{
int field1;
char *field2;
} PyObject;
// Public function pointer type declaration
typedef PyObject *(*__stdcall getPyObject_t)(int arg1, const char *arg2);
#ifdef __cplusplus
}
#endif
#endif // PYOBJECT_DLL_H
Let's suppose that the C code with the exported function is something like:
#include "pyobject.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) PyObject * getPyObject(int arg1, char *arg2);
PyObject *getPyObject(int arg1, char *arg2){
PyObject *obj = (PyObject *)malloc(sizeof(PyObject));
obj->field1 = arg1;
obj->field2 = arg2;
return obj;
}
Finally the C++ code using the function and data created in the library would be:
#include "pyobject.h"
#include <iostream>
#include <windows.h>
int main() {
HINSTANCE dll = LoadLibrary("pyobject.dll");
if (dll == NULL) {
std::cerr << "Cannot open pyobject.dll. Error: " << GetLastError() << "\n";
return 1;
}
getPyObject_t getPyObject = (getPyObject_t) GetProcAddress(dll, "getPyObject");
if (getPyObject == NULL) {
std::cerr << "Cannot locate 'getPyObject' function in dll. Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 2;
}
PyObject *obj = getPyObject(3, "test");
std::cout << "PyObject == { field1: " << obj->field1 << ", field2: \"" << obj->field2 << "\"}\n";
FreeLibrary(dll);
return 0;
}
Edit
As #raymondchen pointed in his comment, ignoring the return type when the C function returns a large aggregate (e.g. struct) it's not a good idea, because the C function expects that the caller already has had reserved stack space to store the returned aggregate, but if the caller treats the function as void or anything else, then compiler will not reserve that space, causing unpredictable effects (probably ending with Segmentation fault error).
To avoid it, it's always better to define the correct type in both C and C++ codes (or in the common header), especially when the C function returns an aggregate.

How do you load a custom module into Lua?

This has been driving me nuts for a long time now. I have followed every tutorial I could find on the internet (here are couple examples[ [1], [2] of the maybe half dozen good ones found via Google search), and still no clear explanation. Although it seems it must be something fairly simple as that lack of a documented explanation implies that it's something most people would take for granted.
How do I load a custom module into Lua?
On the advice of questions like this one, I have written a module that builds a shared library with the expectation that I would be able to load it through a require call. However, when I do that I get undefined symbol errors, despite those exact symbols appearing in the list from the command nm -g mylib.so.
Those two tutorials I linked before aim to create executables that look wrappers of the *.lua file. That is, the built *.exe file should be called to run the Lua program with the custom module.
I understand that these types questions are asked here fairly frequently (as noted in this answer), but I am still at a loss. I tried some of the binding packages (Luabind and OOLua), but those didn't work out great (e.g. my earlier question--which I did ultimately figure out, sort of).
I have implemented a class in C++
I have wrapped the constructors, destructors, and functions with thunks
I have built it errorless-ly as a shared library
Yet no matter what I get undefined symbol: ... errors when I try to load it as mod = require('mylib.so'). How do I do this?
Working Example of a Library of Functions
For the record, just registering a basic function works fine. The below code, when built as libluatest.so, can be run in Lua using the commands:
> require('libluatest')
> greet()
hello world!
libluatest.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
static int greet(lua_State *L)
{
std::cout << "hello world!" << std::endl;
return 0;
}
static const luaL_reg funcs[] =
{
{ "greet", greet},
{ NULL, NULL }
};
extern "C" int luaopen_libluatest(lua_State* L)
{
luaL_register(L, "libluatest", funcs);
return 0;
}
Failing Example of a Class
This is what I am stuck on currently. It doesn't seem to want to work.
myObj.h
#include <string>
class MyObj
{
private:
std::string name_;
public:
MyObj();
~MyObj();
void rename(std::string name);
};
myObj.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
#include "myObj.h"
void MyObj::rename(std::string name)
{
name_ = name;
std::cout << "New name: " << name_ << std::endl;
}
extern "C"
{
// Lua "constructor"
static int lmyobj_new(lua_State* L)
{
MyObj ** udata = (MyObj **)lua_newuserdata(L, sizeof(MyObj));
*udata = new MyObj();
luaL_getmetatable(L, "MyObj");
lua_setmetatable(L, -1);
return 1;
}
// Function to check the type of an argument
MyObj * lcheck_myobj(lua_State* L, int n)
{
return *(MyObj**)luaL_checkudata(L, n, "MyObj");
}
// Lua "destructor": Free instance for garbage collection
static int lmyobj_delete(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
delete obj;
return 0;
}
static int lrename(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
std::string new_name = luaL_checkstring(L, 2);
obj->rename(new_name);
return 0;
}
int luaopen_libmyObj(lua_State* L)
{
luaL_Reg funcs[] =
{
{ "new", lmyobj_new }, // Constructor
{ "__gc", lmyobj_delete }, // Destructor
{ "rename", lrename }, // Setter function
{ NULL, NULL } // Terminating flag
};
luaL_register(L, "MyObj", funcs);
return 0;
}
}
Compiled into libmyObj.so using a simple CMake build with C++11 standard flags on.
Error
> require('libmyObj')
error loading module 'libmyObj' from file './libmyObj.so':
./libmyObj.so: undefined symbol: _ZN5MyObjC1Ev stack traceback: [C]:
? [C]: in function 'require' stdin:1: in main chunk [C]: ?
I am dealing with Lua 5.1 on Ubuntu 14.04.
I am wondering if it has something to do with the mix of C and C++...
It seems that you do not implement:
MyObj() ; ~MyObj();
and be careful with luaopen_* function, since module name is myObj, function name should be luaopen_libmyObj.

dll export function pointer (best way to provide exported function hooking)

I am trying to export a function pointer for a function to be called. What I am after is when a function in a dll/exe needs to call a function exported by another library it gets the function pointer and calls that. The reason for this is I want to provide a hooking mechanism and I figured function pointers would be the quickest and easiest way because I can change what they point to easily are runtime.
So I found this Exporting a function pointer from dll and I cant get it to work. Whenever I call it to get the function pointer I get an error that it cant find the entry point. So the error isnt that the function pointer is working but the function to get the function pointer isnt working. I believe it is a function signature issue. Here is an example:
Colors.h
#ifndef __COLORS
#define __COLORS
#ifdef MYDLL_EXPORTS
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)
#endif
#include <string>
#include <vector>
class Colors
{
private:
std::string myColor;
static DLLEXPORT std::vector<std::string> allColors;
public:
Colors(){};
Colors(std::string MyColor);
virtual DLLEXPORT std::string getMyColor();
virtual DLLEXPORT void addToColors(std::string color);
std::vector<std::string> getAllColors();
};
typedef Colors* (*create)(std::string);
DLLEXPORT create createColors();
Colors* createColors2(std::string color);
#endif
colors.cpp
#define MYDLL_EXPORTS
#include "Color.h"
std::vector<std::string> Colors::allColors;
Colors::Colors(std::string MyColor)
{
this->myColor = MyColor;
this->allColors.push_back(this->myColor);
}
std::vector<std::string> Colors::getAllColors()
{
return this->allColors;
}
std::string Colors::getMyColor()
{
return this->myColor;
}
Colors* createColors2(std::string color)
{
return new Colors(color);
}
DLLEXPORT void Colors::addToColors(std::string color)
{
this->allColors.push_back(color);
}
DLLEXPORT create createColors()
{
return &createColors2;
}
main.cpp
#define MYDLL_EXPORTS
#include <iostream>
#include <Windows.h>
#include "Color.h"
int main()
{
Colors red("red");
Colors blue("blue");
Colors* dlltest;
//Define the function prototype
typedef Colors* (*createNewColor)();
BOOL freeResult, runTimeLinkSuccess = FALSE;
HINSTANCE dllHandle = NULL;
createNewColor dllCreateNewColor = NULL;
//Load the dll and keep the handle to it
dllHandle = LoadLibrary(L"libs/testerdll.dll");
// If the handle is valid, try to get the function address.
if (NULL != dllHandle)
{
//Get pointer to our function using GetProcAddress:
dllCreateNewColor = (createNewColor)GetProcAddress(dllHandle,"createNewColor");
// If the function address is valid, call the function.
if (runTimeLinkSuccess = (NULL != dllCreateNewColor))
{
dlltest = dllCreateNewColor();
std::cout << "Color of dll class: " << dlltest->getMyColor() << std::endl;
}
else
{
std::cout << "Failed to locate function" << std::endl;
}
//Free the library:
//freeResult = FreeLibrary(dllHandle);
}
else
{
std::cout << "Failed to load library" << std::endl;
}
std::vector<std::string> colorslist = red.getAllColors();
for (std::string color : colorslist)
{
std::cout << color << std::endl;
}
return 0;
}
Dll project
dllmain.cpp
// testerdll.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
#include "Color.h"
__declspec(dllexport) Colors* createNewColor()
{
create temp1 = createColors(); //seems to fail here
return nullptr;
}
Yes I know I have memory leaks etc. this was just a quick example code to replicate the problem.
To return the function, you need to get it's address, and return that
e.g.
__declspec(dllexport) create createNewColor()
{
create temp1 = createColors;
return temp1;
}
However, this system (using std::string as a return type, requires that both the .exe and the .dll use the same DLL based runtime library.
stackoverflow : passing reference to STL over function boundary
C++ does not define a calling convention between files. This means that different compilers may set up C++ objects slightly differently. Microsoft limited that with the definition of COM, but that still is a possibility.
Also for visual studio, there are separate heaps (new / delete) between runtime instances. When you link against the dynamic library, all dlls and exes in the process share this DLL. But then they all need to be updated together.
So this process can work, but be wary about :-
Sharing C++ types between binaries (DLL/EXE) - no ABI
Using new in DLL, and delete in EXE. (different heaps).
STL objects are also problematic, as they are a mixture of header implementation (compiled into the binary), and DLL implementation (compiled into C++ runtime).

Passing parameter(s) to function(s) withing different project files in C++

I just am getting confused about passing the parameter to function in C++ over different projects.
I have two different solutions, of which one is a DLL project and another is Console project. Within the first project I have a piece of code as follows:
class __declspec(dllexport) FormatLog
{
public:
void __cdecl ParseFormat(LPCWSTR);
};
The rest of codes are not important herein, whereas in the second project I have the header file consisting of the following code:
class FormatImpl
{
public:
typedef void (__cdecl * FORMAT) (LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) GetProcAddress(hModule, "?ParseFormat#FormatLog##XXXXXXXX#X");
}
}
~FormatImpl()
{
if (hModule != NULL)
{
FreeLibrary(hModule);
}
}
};
When I was calling this from the main function using the following code:
int main(int argc, char* argv[])
{
FormatImpl format;
format.Format(L"%t %m %i %l");
return 0;
}
the parameter became invalid in function void __cdecl ParseFormat(LPCWSTR format); as <Bad Ptr> while inspecting through the Visual Studio 2010.
My question is, if I use GetProcAddress or LoadLibrary to call a .dll file invoking any method, shouldn't I thereby be legitimate to pass any parameter apart from int, double, long or so on to the requested method?
You have a major problem in your code: ParseFormat is not a function taking a LPWSTR and returning void but an instance method of class FormatLog. The difference is that for an instance method, you have a hidden this parameter.
If you have control on first project, the simplest way IMHO is to just use a static method to get rid of the hidden parameter:
class __declspec(dllexport) FormatLog
{
public:
static void __cdecl ParseFormat(LPCWSTR);
};
If you have no control on first project, the correct type for FORMAT would be a pointer to member. Unfortunately I could never find a way to convert the result of GetProcAddress to a pointer to member. Hopefully, it is known that that you can simply get the address of the member function and call it directly, provided you add the hidden this as first parameter. The code would become:
class FormatImpl
{
public:
typedef void (__cdecl *FORMAT) (FormatLog *l, LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) (void *) GetProcAddress(hModule,
"?ParseFormat#FormatLog##QAAXPB_W#Z");
}
}
...
}
(after getting the mangled name in FormatLog.exp) and you will use it like that:
int main(int argc, char* argv[])
{
FormatImpl format;
FormatLog l;
format.Format(&l, L"%t %m %i %l");
return 0;
}
Anyway, I generally think that the mangled names should be an implementation detail and I only export extern "C" functions from a DLL if I later want to import them manually through GetProcAddress.
So my advice would be to add in first project:
extern "C" {
__declspec(dllexport) void __cdecl doParseFormat(LPWSTR str) {
static FormatLog flog;
flog.ParseFormat(str);
}
}
Now you can simply write:
Format = (FORMAT) GetProcAddress(hModule, "doParseFormat");
which I personnaly find more clean, and you can use it easily.

Including C-DLL from C++

This feels like a noob question, so if it's a dupe, please point me to the right location :)
I tried including a DLL written in C into a C++ program. It didn't work; gcc said
test.cpp: xxx: error: too many arguments to function.
Here's a minimal working example:
Wrapper for DLL functions:
/* myWrapper.h */
#ifndef _MYWRAPPER_H
#define _MYWRAPPER_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers();
#ifdef __cplusplus
}
#endif
#endif
Implementation thereof:
/* myWrapper.c */
#include <windows.h>
#include "myHeader.h"
#ifdef __cplusplus
extern "C" {
#endif
HINSTANCE drvsHANDLE;
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers()
{
static int result;
drvsHANDLE = LoadLibrary("myLibrary.dll");
if (drvsHANDLE == NULL) return (result=0);
EXPORTED_functionNameP = GetProcAddress(
drvsHANDLE, "originalFunctionName");
if (EXPORTED_functionNameP == NULL) return (result = 0);
return (result = 1);
}
#ifdef __cplusplus
}
#endif
Naturally, I haven't written these nor the library myself, and preferably, they should all stay untouched. I did however add the extern "C" lines.
Then, my main file:
// my Main
#include <windows.h>
#include "myHeader.h"
int main(int argc, char **argv)
{
int arg = 1;
EXPORTED_functionNameP(arg);
return 0;
}
Build commands:
gcc -I. -c -o myHeader.o myHeader.c -L. -lmyLibrary
g++ -I. -o main.exe myMain.cpp myHeader.o -L. -lmyLibrary
It works fine if I rewrite my main.cpp into valid C and compile with gcc instead of g++.
I tried changing extern "C" into extern "C++" to no avail, I tried all permutations or gcc and g++ for the two build commands, nothing.
I know it's something to do with name mangling, but I thought gcc would take care of that when you include the extern "C" lines...Can someone please explain what I'm missing here?
In case it matters --
Windows XP Pro (will be Win7 later on)
(MinGW) gcc 4.6.2
I know this is a very old question, but I am having exactly the same issues but in relation to writing a generic wrapper template for wrapping calls to LoadLibrary() and GetProcAddress()
Taking https://blog.benoitblanchon.fr/getprocaddress-like-a-boss/ as inspiration, it looks like he is taking FARPROC as a kind of "void* for Windows functions" and then casting it to the correct type subsequently.
I needed to tweak that code a little to work for me, and reproduce it here:
class ProcPtr
{
public:
explicit ProcPtr(FARPROC ptr) : m_ptr(ptr) {}
template <typename T>
operator T* () const { return reinterpret_cast<T*>(m_ptr); }
private:
FARPROC m_ptr;
};
class DllHelper
{
public:
explicit DllHelper(LPCTSTR filename) : m_module(LoadLibrary(filename)) {}
~DllHelper() { FreeLibrary(m_module); }
ProcPtr operator[](LPCSTR proc_name) const
{
return ProcPtr(::GetProcAddress(m_module, proc_name));
}
private:
HMODULE m_module;
};
So, with that helper code now available we can use it to write a wrapper class that encapsulates several functions in the Advapi32 library:
class Advapi32
{
public:
Advapi32() : m_dll(TEXT("Advapi32"))
{
getUserName = m_dll["GetUserNameA"];
openSCManager = m_dll["OpenSCManagerA"];
bogusFunction = m_dll["BogusFunctionThatDoesNotExist"];
}
decltype(GetUserNameA)* getUserName;
decltype(OpenSCManagerA)* openSCManager;
decltype(GetWindowsDirectoryA)* bogusFunction;
private:
DllHelper m_dll;
};
bogusFunction is a function with the same signature as GetWindowsDirectoryA but which doesn't exist in Advapi32. This is what I was trying to achieve - graceful fallback on an older OS which might not have a certain function.
So, finally a test app...
int main()
{
Advapi32 advapi32;
auto func1 = advapi32.getUserName;
if (func1)
{
TCHAR infoBuf[256];
DWORD bufCharCount = sizeof(infoBuf);
if (func1(infoBuf, &bufCharCount))
{
std::cout << "Username: " << infoBuf << std::endl;
}
}
auto func2 = advapi32.openSCManager;
if (func2)
{
SC_HANDLE handle = func2(NULL, NULL, SC_MANAGER_CONNECT);
if (handle)
{
std::cout << "opened SC Manager" << std::endl;
}
}
auto func3 = advapi32.bogusFunction;
if (func3)
{
std::cerr << "This should not happen!" << std::endl;
}
else
{
std::cout << "Function not supported" << std::endl;
}
}
Output:
Username: TestAccount
opened SC Manager
Function not supported
Note: This was compiled as a Windows 32-bit console application with MBCS rather than Unicode, under VS2019 with the VS2015_XP toolset, since that is what I am needing to target (don't ask).
The FARPROC type is a function pointer for a function that takes no parameters. You should declare EXPORTED_functionNameP like so (replacing void with whatever the function really returns):
extern void (*EXPORTED_functionNameP)(int);
And initialize it like so (the returned value from GetProcAddress() pretty much always needs to be cast to the correct type):
EXPORTED_functionNameP = (void (*)(int)) GetProcAddress(drvsHANDLE, "originalFunctionName");
A typedef for the funciton type might make things a bit more readable.
There is a difference between C and C++.
int (FAR WINAPI * FARPROC) ()
In C, the FARPROC declaration indicates a callback function that has an unspecified parameter list. In C++, however, the empty parameter list in the declaration indicates that a function has no parameters.
The MSDN page on CallWindowProc explains a bit more.
After a quick Google search, it seems that FARPROC is defined as this:
typedef int (FAR WINAPI *FARPROC)();
That is, FARPROC is a function that returns an int and takes no arguments. So you can't use it for any other case.
Instead declare EXPORTED_functionNameP like this:
extern void (*EXPORTED_functionNameP)(int);
Now EXPORTED_functionNameP is a pointer to a function that takes an int argument and returns no value.
It is because of FARPROC is defined as:
int (FAR WINAPI * FARPROC) ()
So you can not pass any parameters to such function in C++. For fix it you should define EXPORTED_functionNameP as pointer to function with equal semantics as defined in DLL-library. For example:
typedef (void* EXPORTED_functionNameP)(int value);
EXPORTED_functionNameP ExportedFns;
...
ExportedFns = GetProcAddress(drvsHANDLE, "originalFunctionName");
FARPROC is defined as
typedef int (FAR WINAPI *FARPROC)();
When you pass an additional argument although the argument list of the prototype is empty you get the error.
You need a proper prototype definition for PORTED_functionNameP and cas the result from GetProcAddress to that type in your GetDLLPopinters functions.