I need to implement some functionality of the otherwise monolithic application via DLL that is loaded at runtime. (Think about a customized DLL -- different for each customer.)
The Visual C++ from VS 2013 is used.
The application gets the full name name of the DLL. The function to be called has a fixed name (convert
in my case) and fixed number and type of the arguments (a reference to a constant vector of strings -- see the cref_vs
below). This means the function is implemented in C++.
I have modified the example from the MSDN doc, and it seems to work. However, I must be sure I did not overlooked something important. Here is the code (simplified) to load the DLL and call the function:
typedef const std::vector<std::string> & cref_vs;
typedef int(*CONVERTPROC)(cref_vs vs);
Notice that unlike in the official example that mixes calling a C code in DLL from a C++ function, I do not use __cdecl
. I guess that this way I can reliably pass a C++ object (like a vector of strings). Is it correct?
int call_convert_from_dll(const std::string & dllname,
const std::vector<std::string> & vs)
{
HINSTANCE hinstLib;
CONVERTPROC convert;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(dllname.c_str());
// If the handle is valid, try to get the function address.
if (hinstLib != nullptr) {
convert = (CONVERTPROC)GetProcAddress(hinstLib, "convert");
// If the function address is valid, call the function.
if (convert != nullptr) {
(convert)(vs);
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
if (!fRunTimeLinkSuccess)
return 1;
return 0;
}
Now, because I want the unmangled name of the function inside the DLL, I need to use extern "C"
, and it must be exported via __declspec(dllexport)
. However, I do not want to use __cdecl
calling convention:
#include <windows.h>
#include <iostream>
using namespace std;
extern "C" {
__declspec(dllexport) int convert(const std::vector<std::string> & vs)
{
cout << "my.dll -- convert called with arguments:\n";
for (int i = 0; i < argc; ++i)
cout << argv[i] << endl;
return 0;
}
} // extern "C"
Can you confirm that I am doing it correctly?