c++ - 有没有更好的方法在 C++ 中加载 dll?

标签 c++ windows dll loadlibrary

现在我正在做这样的事情,如果我最终有很多我想在我的 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 的方法:

  1. Run-Time Dynamic Linking (你现在在做什么)
  2. Load-Time Dynamic Linking (使用 DLL 的“典型”方式)
  3. Delay-Load Dynamic Linking
  4. DLL Forwarding

我不必解释运行时动态链接,因为您已经在解释了。我选择不解释延迟加载动态链接,除了一般性地描述它是什么。延迟加载本质上与加载时动态链接相同,只是它是即时完成的,而不是在应用程序加载时完成的。这并不像您想象的那样有用或有益,它很难使用并且很难编写代码。所以我们不要去那里,至少现在不要去。 DLL 转发 甚至比延迟加载更奇特——如此奇特,直到@mox 在评论中提到它,我才听说过它。我会让你阅读上面的链接来了解它,但只要说 DLL 转发就是当你在一个 DLL 中调用一个导出函数但该请求实际上被转发到一个 DLL 中的另一个函数就足够了不同的 DLL。

加载时动态链接

这就是我认为的普通 DLL 链接

这是大多数人在提及在其应用程序中使用 DLL 时所指的内容。您只需#include DLL 的头文件并链接到LIB 文件。无需 GetProcAddress() 或创建函数指针类型定义。简而言之,它是如何工作的:

  1. 您通常会得到 3 个文件:一个包含运行时代码的 DLL、一个 LIB 文件和一个头文件。头文件只是一个头文件 -- 它描述了您可以使用的 DLL 中的所有功能。

  2. 您编写应用程序时,#include从 DLL 中获取头文件并调用这些函数,就像您在任何头文件中使用任何函数一样。编译器知道您使用的函数和对象的名称,因为它们在 DLL 的头文件中。但它还不知道它们在内存中的位置。这就是 LIB 文件的来源...

  3. 您转到项目的链接器设置并添加“附加库依赖项”,指定 LIB 文件。 LIB 文件告诉链接器您使用的 H 文件中的函数和对象在内存中的位置(显然是相对而言,而不是绝对术语)。

  4. 编译您的应用。如果您已正确设置所有内容,它应该可以编译、链接和运行。当您收到“未解析的外部引用”链接器错误时,通常这是由于设置不正确造成的。您可能没有指定正确的 LIB 文件路径,或者您需要包含更多 LIB 文件。

关于c++ - 有没有更好的方法在 C++ 中加载 dll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2060403/

相关文章:

asp.net - 我如何使用 wkhtmltopdf(dll 版本)asp.net?

c++ - 缓冲区被覆盖

c++ - 多平台原子增量

c - 为什么这个 C 代码在没有 cygwin 的情况下可以在 linux 上运行,但不能在 Windows 上运行

Java:使用 char** 和回调作为参数加载 c++ dll

javascript - 有没有办法为 node.js 的 golang 库创建绑定(bind)?

c++ - pthread_spinlock 是否会导致从用户空间切换到内核空间

c++ - 交叉编译 Ubuntu 到 Beaglebone 后无法在目标上找到共享库

windows - Windows XP/fiber.node 上的 Meteor 失败

c++ - 如何在 Windows 上将 GoogleTest 变量 GTEST_LIBRARY GTEST_INCLUDE_DIR 和 GTEST_MAIN_LIBRARY 设置为 CMake?