【问题标题】:Calling functions in a DLL from C++从 C++ 调用 DLL 中的函数
【发布时间】:2010-10-07 01:32:14
【问题描述】:

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

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

我怎么称呼它?

【问题讨论】:

    标签: c++ visual-studio-2008 dll dllimport


    【解决方案1】:

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

    CAVEAT:定义文件方法最适合未修饰符号名称。如果你想导出修饰符号,那么最好不使用定义文件方法。

    这里有一个简单的例子说明如何做到这一点。

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

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

    第二步:export.cpp文件中定义函数。

    #include <windows.h>
    
    int WINAPI IsolatedFunction(const char *title, const char *test)
    {
        MessageBox(0, title, test, MB_OK);
        return 1;
    }
    

    第 3 步:将函数定义为 export.def 定义文件中的导出。

    EXPORTS    IsolatedFunction          @1
    

    步骤 4: 创建一个 DLL 项目并将 export.cppexport.def 文件添加到该项目中。构建这个项目将创建一个 export.dll 和一个 export.lib 文件。

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

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

    第 6 步:从 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跨度>
    • 第 6 步还需要 #include
    • 您是正确的,需要 windows.h。在上面的示例中,我使用的是 #include "stdafx.h" 文件,它是预编译的头文件。在这种情况下,该文件包含 windows.h 包含。
    • 是的,你是对的,我创建了 Win32 控制台应用程序,这就是为什么我的没有,而你创建了 Win32 项目,所以你在 stdafx.h 中拥有它。只知道区别。谢谢
    • 那么.lib 文件是否包含之前创建的.h 文件接口?我遇到了这篇文章,试图弄清楚为什么我拥有的东西无法编译。我想知道在构建使用外部库的程序时找不到 .h 文件是否意味着没有正确找到 dll 的 .lib 文件。
    【解决方案2】:

    还可以从dll导出函数,从exe导入,一开始比较棘手,但最终比调用LoadLibrary/GetProcAddress容易得多。见MSDN

    使用 VS 向导创建项目时,dll 中有一个复选框,可让您导出函数。

    然后,在 exe 应用程序中,您只需 #include 来自 dll 的具有正确定义的标头,并将 dll 项目作为依赖项添加到 exe 应用程序。

    如果您想进一步调查这一点,请查看其他问题Exporting functions from a DLL with dllexport

    【讨论】:

      【解决方案3】:

      您可以使用 LoadLibrary/GetProcAddress 路由(正如 Harper 在他的回答中提到的,这里再次链接到 run-time dynamic linking MSDN sample ),或者您可以将您的控制台应用程序链接到从 DLL 项目生成的 .lib 并包含 hea。 h 文件,其中包含函数的声明(如 load-time dynamic linking MSDN sample 中所述)

      在这两种情况下,您都需要确保您的 DLL 正确导出您想要调用的函数。最简单的方法是在函数声明中使用 __declspec(dllexport)(如创建simple dynamic-link library MSDN sample 所示),但您也可以通过 DLL 项目中相应的 .def 文件来实现。

      有关 DLL 主题的更多信息,您应该浏览 MSDN About Dynamic-Link Libraries 主题。

      【讨论】:

        【解决方案4】:

        以下是所需的 5 个步骤:

        1. 声明函数指针
        2. 加载库
        3. 获取程序地址
        4. 将其分配给函数指针
        5. 使用函数指针调用函数

        您可以在http://www.softwareandfinance.com/Visual_CPP/DLLDynamicBinding.html找到逐步的 VC++ IDE 屏幕截图

        这里是sn-p的代码:

        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;
        }
        

        【讨论】:

          【解决方案5】:

          可能有用:https://www.codeproject.com/Articles/6299/Step-by-Step-Calling-C-DLLs-from-VC-and-VB-Part-4

          对于上面带有“GetWelcomeMessage”的示例,如果在调用导入的函数后出现错误,您可能需要在函数名称之前的 typedef 字段中指定“__stdcall”。

          【讨论】:

            【解决方案6】:

            假设您正在讨论 DLL 的动态运行时加载,您正在寻找 LoadLibrary 和 GetProAddress。 MSDN 上有一个例子。

            【讨论】:

              【解决方案7】:

              当创建 DLL 时,通常会自动创建一个导入库,您应该使用链接到程序的头文件以及头文件来调用它,但如果没有,您可以手动调用 Windows 函数,如 LoadLibraryGetProcAddress让它工作。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-11-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-06-16
                • 1970-01-01
                • 2012-06-23
                相关资源
                最近更新 更多