I'm trying to create a very simple dll and load it to another file for learning purpose. I'm using VC++ same version for both the DLL and the C++ file. Here is my source code:
load.cpp:
#include <iostream>
#include <windows.h>
using namespace std;
typedef int(__stdcall* nsum)(int a, int b);
int main(void)
{
HINSTANCE myDll = LoadLibrary(L".\\DLL1.dll");
nsum sum = (nsum)GetProcAddress(myDll, "sum");
if (!myDll) {
cout << "could not load the dynamic library" << endl;
return EXIT_FAILURE;
}
int xfinal = sum(10, 20);
cout << xfinal << endl;
return 0;
}
and dll.cpp
#include <windows.h>
#include "pch.h"
using namespace std;
int __declspec(dllexport) __stdcall sum(int a, int b)
{
return a + b;
}
pch.h
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
But still I'm getting the exception. I searched for answers but found none, so I am writing this for help
In the load.cpp, in HINSTANCE myDll, I can peek and see the value being set to 0x000000000. Is it the reason? If so, How can i fix it?
Your problem is quite simple. The exported name of your function is not sum
because you are not use a C ABI . Instead, it's a mangled name ?sum@@YGHHH@Z
which of course is not found by your use of GetProcAddress(myDLL, "sum");
There is no such function sum . As such, you are trying to invoke a function at address 0, ie exactly what the exception tells you.
Microsoft calls these Decorated Names rather than "mangled" but they both mean the same thing: the type information for the parameter types, calling-convention, and return value is encoded into special symbols that make up the name.
A few options here to fix this problem:
Use the import library instead of explicit linking which will use the mangled name so you can stick with a C++ ABI.
Use a C ABI via extern "C"
keeping the existing __stdcall
calling convention in which case the name will be _sum@8
when building for x86 (32-bit):
extern "C" int __declspec(dllexport) __stdcall sum(int a, int b)
extern "C"
but use __cdecl
which will actually result in sum
for x86 (32-bit):extern "C" int __declspec(dllexport) __cdecl sum(int a, int b)
For x64 there is one standard calling convention __fastcall
( __cdecl
, __stdcall
are just aliases for __fastcall
). In that, just using extern "C"
will result in the name sum
for any of those calling conventions. The only case that results in 'mangled' exports using a C ABI for x64 then is extern "C" __vectorcall
.
Be sure to update your typedef to match the calling convention you are using if you change it.
Second, you should add more error-checking:
HMODULE myDll = LoadLibrary(L".\\DLL1.dll");
if (!myDll) {
cout << "could not load the dynamic library" << endl;
return EXIT_FAILURE;
}
nsum sum = (nsum)GetProcAddress(myDll, "sum");
if (!sum) {
cout << "could not find the export" << endl;
return EXIT_FAILURE;
}
If you are using C++11 or later (Visual Studio 2012 or later), then
auto sum = reinterpret_cast<nsum>(reinterpret_cast<void*>(GetProcAddress(myDll, "sum")));
is better.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.