从C++调用DLL中的函数

43

我有一个在VS 2008中的解决方案,其中包含两个项目。一个是用C++编写的DLL,另一个是从空白项目创建的简单C++控制台应用程序。我想知道如何从应用程序中调用DLL中的函数。

假设我从一个空白的C++项目开始,并且我想调用一个名为int IsolatedFunction(int someParam)的函数。

我该如何调用它呢?

7个回答

22

有很多方法可以实现这一目的,但我认为最简单的方法之一是在链接时将应用程序链接到 DLL,然后使用 定义文件 来定义要从 DLL 导出的符号。

注意:定义文件方法最适合于 未装饰 的符号名称。如果你想导出修饰过的符号,则最好不要使用定义文件方法。

以下是一个简单的示例,说明如何完成这个过程。

第一步:export.h文件中定义函数。

int WINAPI IsolatedFunction(const char *title, const char *test);

步骤2:export.cpp文件中定义函数。

#include <windows.h>

int WINAPI IsolatedFunction(const char *title, const char *test)
{
    MessageBox(0, title, test, MB_OK);
    return 1;
}

第三步:export.def 定义文件中将该函数定义为一个导出项。

EXPORTS    IsolatedFunction          @1

第四步: 创建一个DLL项目,并将export.cppexport.def文件添加到该项目中。构建此项目将创建一个export.dll和一个export.lib文件。

以下两个步骤在链接时连接到DLL。如果您不想在链接时定义入口点,请忽略下面的两个步骤并使用LoadLibraryGetProcAddress在运行时加载函数入口点。

第五步: 创建一个Test应用程序项目,通过将export.lib文件添加到项目中来使用dll。将export.dll文件复制到与Test控制台可执行文件相同的位置。

第六步: 在Test应用程序中调用IsolatedFunction函数,如下所示。

#include "stdafx.h"

// get the function prototype of the imported function
#include "../export/export.h"

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    // call the imported function found in the dll
    int result = IsolatedFunction("hello", "world");

    return 0;
}

除了将export.def文件添加到该项目中,我还需要在链接器->输入->模块定义文件中指向.def文件,例如$(SolutionDir)export.def。 - V-SHY
1
你还需要在第6步中加入 #include <windows.h>。 - V-SHY
1
你说得对,windows.h 是必需的。在上面的例子中,我使用了 #include "stdafx.h" 文件,这是预编译头文件。在这种情况下,该文件包含了 windows.h 的引用。 - jussij
2
是的,你说得对,我创建了Win32控制台应用程序,所以我的没有,而你创建了Win32项目,所以你在stdafx.h中有它。只要知道这个区别就好了。谢谢。 - V-SHY
那么.lib文件是否包含之前创建的.h文件接口呢? 我在查找为什么我的某个东西无法编译时遇到了这篇文章。我想知道,如果在构建使用外部库的程序时找不到.h文件,是否意味着未能正确找到dll的.lib文件。 - James Joshua Street
James Joshua Street写道:“那么.lib文件是否包含之前创建的.h文件接口?”不是的。.h文件由编译器使用,而.lib文件由链接器使用。 - veight

9
也可以从dll中导出函数并从exe中导入,一开始可能比调用LoadLibrary/GetProcAddress更棘手,但最终比后者更容易。请参阅MSDN
使用VS向导创建项目时,在dll中有一个复选框可让您导出函数。
然后,在exe应用程序中,您只需要#include来自具有适当定义的dll的标头,并将dll项目添加为exe应用程序的依赖项。
如果您想进一步研究此问题,请查看Exporting functions from a DLL with dllexport这个问题。

7
以下是需要完成的5个步骤:
  1. 声明函数指针
  2. 加载库文件
  3. 获取过程地址
  4. 将其分配给函数指针
  5. 使用函数指针调用函数
您可以在此处找到VC ++ IDE逐步截图。
以下是代码片段:
int main()
{
/***
__declspec(dllimport) bool GetWelcomeMessage(char *buf, int len); // used for static binding
 ***/
    typedef bool (*GW)(char *buf, int len);

    HMODULE hModule = LoadLibrary(TEXT("TestServer.DLL"));
    GW GetWelcomeMessage = (GW) GetProcAddress(hModule, "GetWelcomeMessage");

    char buf[128];
    if(GetWelcomeMessage(buf, 128) == true)
        std::cout << buf;
        return 0;
}

6
您可以选择使用LoadLibrary/GetProcAddress方法(如Harper在他的回答中提到的,这里是链接到运行时动态链接MSDN示例的链接),或者将控制台应用程序链接到从DLL项目生成的.lib文件,并包含具有函数声明的hea.h文件(如加载时动态链接MSDN示例中所述)。
在这两种情况下,您需要确保您的DLL正确导出要调用的函数。最简单的方法是在函数声明上使用__declspec(dllexport)(如创建一个简单的动态链接库MSDN示例中所示),尽管您还可以通过相应的.def文件在DLL项目中完成它。

如果您想了解关于DLL的更多信息,您可以浏览MSDN 关于动态链接库主题。


1

0

假设你在讨论动态运行时加载DLL,那么你应该使用LoadLibrary和GetProAddress。可以在MSDN看到一个例子。


0

当 DLL 被创建时,通常会自动创建一个导入库,您应该将其与头文件一起链接到程序中进行调用,但如果没有,则可以手动调用 Windows 函数,如 LoadLibraryGetProcAddress 以使其正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接