从控制台应用程序动态使用 DLL
Dynamically use a DLL from a console application
我正在尝试创建一个库 Lib.dll
以从控制台应用程序动态调用,但找不到我要调用的函数 funci()
。
Lib.dll
是 Visual Studio 2019 年创建的项目(控制台应用程序,但设置为配置类型:.dll)的成果。
Lib.cpp
是该项目中唯一的文件,并且只包含代码:
__declspec(dllexport) int funci()
{
return 50;
}
我认为我正在正确导出函数,因为我使用 DLL Export Viewer v1.66 找到了函数。
但是,我很难通过我的控制台应用程序 (.exe) 找到该功能:
#include <windows.h>
#include <iostream>
typedef int(__cdecl* o_funci)(void);
o_funci funci;
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\Lib.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
funci = (o_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;
FreeLibrary(hGetProcIDDLL);
}
GetProcAddress
出现问题,但不知道原因。我哪里错了?
输出:
我一直在看这个旧的post:Dynamically load a function from a DLL
编辑:感谢 tenfour
解决了
我使用了 DependencyWalker。
没有 extern "C"
我可以看到未修饰的 funci
的名字是 ?funci@@YGHXZ
,
所以 funci = (o_funci)GetProcAddress(hGetProcIDDLL, "?funci@@YGHXZ");
成功了。
与 extern "C"
一起,未修饰的 funci
的名称为 _funci@0
- 更干净一些。
另一个注意事项;使用序数 0x0001
在这两种情况下都有效。像这样:funci = (o_funci)GetProcAddress(hGetProcIDDLL, (PCSTR)0x0001);
您使用的工具显示的是导出名称的漂亮版本。它的真实名称将包含名称修改,这是一种将调用信息嵌入到导出名称中的复杂尝试。
您有多种选择可以使这项工作与 GetProcAddress
:
- 使用真实的导出名称。您的工具可能可以选择查看未美化的名称(损坏的导出名称)
- 使用模块定义文件 (*.def) 导出函数,您甚至可以在其中指定导出的名称
- 按序号而不是名称导入
- 将函数包装在
extern "C" { ... }
中,这将使用 C 风格命名,从而避免名称混淆。
最常见的解决方案可能是#4,紧随其后的是#2。
我正在尝试创建一个库 Lib.dll
以从控制台应用程序动态调用,但找不到我要调用的函数 funci()
。
Lib.dll
是 Visual Studio 2019 年创建的项目(控制台应用程序,但设置为配置类型:.dll)的成果。
Lib.cpp
是该项目中唯一的文件,并且只包含代码:
__declspec(dllexport) int funci()
{
return 50;
}
我认为我正在正确导出函数,因为我使用 DLL Export Viewer v1.66 找到了函数。
但是,我很难通过我的控制台应用程序 (.exe) 找到该功能:
#include <windows.h>
#include <iostream>
typedef int(__cdecl* o_funci)(void);
o_funci funci;
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\Lib.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
funci = (o_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;
FreeLibrary(hGetProcIDDLL);
}
GetProcAddress
出现问题,但不知道原因。我哪里错了?
输出:
我一直在看这个旧的post:Dynamically load a function from a DLL
编辑:感谢 tenfour
解决了我使用了 DependencyWalker。
没有 extern "C"
我可以看到未修饰的 funci
的名字是 ?funci@@YGHXZ
,
所以 funci = (o_funci)GetProcAddress(hGetProcIDDLL, "?funci@@YGHXZ");
成功了。
与 extern "C"
一起,未修饰的 funci
的名称为 _funci@0
- 更干净一些。
另一个注意事项;使用序数 0x0001
在这两种情况下都有效。像这样:funci = (o_funci)GetProcAddress(hGetProcIDDLL, (PCSTR)0x0001);
您使用的工具显示的是导出名称的漂亮版本。它的真实名称将包含名称修改,这是一种将调用信息嵌入到导出名称中的复杂尝试。
您有多种选择可以使这项工作与 GetProcAddress
:
- 使用真实的导出名称。您的工具可能可以选择查看未美化的名称(损坏的导出名称)
- 使用模块定义文件 (*.def) 导出函数,您甚至可以在其中指定导出的名称
- 按序号而不是名称导入
- 将函数包装在
extern "C" { ... }
中,这将使用 C 风格命名,从而避免名称混淆。
最常见的解决方案可能是#4,紧随其后的是#2。