现在我正在做这样的事情,如果我最终有很多我想在我的 DLL 中引用的函数,这看起来很乱。有没有更好更简洁的方法来访问函数而不必为每个函数定义创建 typedef 以便它可以正确编译和加载函数。我的意思是函数定义已经在 .h 文件中,我不应该在加载函数后重新声明它们(或者我这样做?)有没有比使用 LoadLibary 更好的解决方案?如果我可以在 Visual Studio 2005 项目设置中做同样的事情,我不一定需要该功能。
BHannan_Test_Class.h
#include "stdafx.h"
#include <windows.h>
#ifndef BHANNAN_TEST_CLASS_H_
#define BHANNAN_TEST_CLASS_H_
extern "C" {
// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int __declspec (dllexport) Factorial(int n);
// Returns true iff n is a prime number.
bool __declspec (dllexport) IsPrime(int n);
}
#endif // BHANNAN_TEST_CLASS_H_
BHannan_Test_Class.cpp
#include "stdafx.h"
#include "BHannan_Test_Class.h"
// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int Factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
// Returns true iff n is a prime number.
bool IsPrime(int n) {
// Trivial case 1: small numbers
if (n <= 1) return false;
// Trivial case 2: even numbers
if (n % 2 == 0) return n == 2;
// Now, we have that n is odd and n >= 3.
// Try to divide n by every odd number i, starting from 3
for (int i = 3; ; i += 2) {
// We only have to try i up to the squre root of n
if (i > n/i) break;
// Now, we have i <= n/i < n.
// If n is divisible by i, n is not prime.
if (n % i == 0) return false;
}
// n has no integer factor in the range (1, n), and thus is prime.
return true;
}
dll_test.cpp
#include <BHannan_Test_Class.h>
typedef int (*FactorialPtr) (int);
FactorialPtr myFactorial=NULL;
// Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {
HMODULE myDLL = LoadLibrary("BHannan_Sample_DLL.dll");
if(myDLL) {
myFactorial = (FactorialPtr) GetProcAddress(myDLL,"Factorial");
if(myFactorial)
{
EXPECT_EQ(1, myFactorial(-5));
EXPECT_EQ(1, myFactorial(-1));
EXPECT_TRUE(myFactorial(-10) > 0);
}
FreeLibrary(myDLL);
}
}
最佳答案
在 Windows 世界中,有(至少)4 种使用 DLL 的方法:
- Run-Time Dynamic Linking (你现在在做什么)
- Load-Time Dynamic Linking (使用 DLL 的“典型”方式)
- Delay-Load Dynamic Linking
- DLL Forwarding
我不必解释运行时动态链接,因为您已经在解释了。我选择不解释延迟加载动态链接,除了一般性地描述它是什么。延迟加载本质上与加载时动态链接相同,只是它是即时完成的,而不是在应用程序加载时完成的。这并不像您想象的那样有用或有益,它很难使用并且很难编写代码。所以我们不要去那里,至少现在不要去。 DLL 转发 甚至比延迟加载更奇特——如此奇特,直到@mox 在评论中提到它,我才听说过它。我会让你阅读上面的链接来了解它,但只要说 DLL 转发就是当你在一个 DLL 中调用一个导出函数但该请求实际上被转发到一个 DLL 中的另一个函数就足够了不同的 DLL。
加载时动态链接
这就是我认为的普通 DLL 链接。
这是大多数人在提及在其应用程序中使用 DLL 时所指的内容。您只需#include
DLL 的头文件并链接到LIB 文件。无需 GetProcAddress()
或创建函数指针类型定义。简而言之,它是如何工作的:
您通常会得到 3 个文件:一个包含运行时代码的 DLL、一个 LIB 文件和一个头文件。头文件只是一个头文件 -- 它描述了您可以使用的 DLL 中的所有功能。
您编写应用程序时,
#include
从 DLL 中获取头文件并调用这些函数,就像您在任何头文件中使用任何函数一样。编译器知道您使用的函数和对象的名称,因为它们在 DLL 的头文件中。但它还不知道它们在内存中的位置。这就是 LIB 文件的来源...您转到项目的链接器设置并添加“附加库依赖项”,指定 LIB 文件。 LIB 文件告诉链接器您使用的 H 文件中的函数和对象在内存中的位置(显然是相对而言,而不是绝对术语)。
编译您的应用。如果您已正确设置所有内容,它应该可以编译、链接和运行。当您收到“未解析的外部引用”链接器错误时,通常这是由于设置不正确造成的。您可能没有指定正确的 LIB 文件路径,或者您需要包含更多 LIB 文件。
关于c++ - 有没有更好的方法在 C++ 中加载 dll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2060403/