【问题标题】:How to use DLL without header in C++如何在 C++ 中使用没有头文件的 DLL
【发布时间】:2011-10-23 06:23:25
【问题描述】:

请帮忙。 A 有一个 dll 文件。我知道它的功能和参数。如何在 Eclipse 中使用 MinGW?

【问题讨论】:

  • LoadLibrary 然后GetProcAddress 可以使用。
  • 要让这些工具来完成我们的竞标总是很困难的。如果全部记录的话,它总是记录得很差。而在你成功之后,你会忘记如何,直到五年后。等等。如果您想静态链接(这意味着,链接器添加引用,加载器执行 DLL 绑定),您可以从查看模块定义文件开始。也许您的工具链支持它们。
  • 通常,如果你有函数名和参数,但没有the头,最简单的解决办法就是写a 自己标头。 (您还需要知道调用约定,但无论如何都是必需的)

标签: c++ eclipse winapi dll mingw


【解决方案1】:

我假设您使用的是 Windows。在 WINAPI 中,您有 LoadLibraryGetProcAddress 函数。这是example 的用法

【讨论】:

  • 不可能将 dll 的路径添加到编译器属性或其他地方,例如静态库?
  • @Country 静态库需要标头才能知道要调用什么。
  • @Deanna 是的,但我说的是动态的
  • 你能得到关于函数API的完整信息吗?就像 DLL 本身是否存储有关它期望的参数类型和返回类型的信息,还是该信息仅包含在头文件中?
  • 如果函数导出为 C++,那么名称修饰将表示参数及其类型,您可以使用各种工具将函数名称“解开”到原型。如果函数导出为 C,则无法判断参数或其类型是什么。
【解决方案2】:

我知道您知道 DLL 函数签名,但您没有标头。

对于具有已知签名的给定函数dll_function

long dll_function(long, long, char*, char*);

您可以使用 Windows API 中的 LoadLibraryGetProcAddress,如以下 C++ 代码所示:

#include <windows.h>
#include <iostream>

typedef long(__stdcall *f_funci)(long, long, char*, char*);


struct dll_func_args {
    long arg1;
    long arg2;
    std::string arg3;
    std::string arg4;
};

// Borrowing from https://stackoverflow.com/a/27296/832621
std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

int main()
{
    std::string filename = "C:\\...\\mydllfile.dll";
    dll_func_args args;
    args.arg1 = 1;
    args.arg2 = 2;
    args.arg3 = "arg3";
    args.arg4 = "arg4";

   std::wstring tmp = s2ws(filename);
    HINSTANCE hGetProcIDDLL = LoadLibrary(tmp.c_str());

    if (!hGetProcIDDLL)
    {
        std::cerr << "Failed to load DLL" << std::endl;
        return EXIT_FAILURE;
    }

    // resolve function address here
    dll_func_ptr func = (dll_func_ptr)GetProcAddress(hGetProcIDDLL, "dll_function");
    if (!func)
    {
        std::cout << "Failed to load function inside DLL" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "Return value " << func(args.arg1, args.arg2, (char *)args.arg3.c_str(), (char *)args.arg4.c_str()) << std::endl;

    return EXIT_SUCCESS;
}

【讨论】:

    【解决方案3】:

    如果您确实有适当的 .LIB 文件,并且您有确切的函数原型,则不需要标头。只需自己声明函数(可能在您自己的自定义标头中)。直接调用这些函数。与 .LIB 文件链接。 DLL 将被操作系统加载,并调用函数。

    如果您没有 .LIB 文件来链接到 DLL,则需要按照其他人的建议使用 LoadLibraryGetProcAddress

    【讨论】:

      【解决方案4】:

      不久前我创建了一个wrapper 来简化这类事情。

      更新:我完全忘记了这篇文章,并删除了博客文章和相关的源代码。我在这里得到了一个悬空指针;-)

      幸运的是,有人比我做得更好:Boost.DLL

      【讨论】:

      • 只是出于好奇,你还在某处(7 年后)有那个包装器吗?该网站已关闭:)
      • @DmitryAvtonomov - 恐怕不会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多