c++ - GetProcAddress 用于将修饰的 C++ 函数导入到 C++ 中

标签 c++ dll dllexport loadlibrary getprocaddress

在 Visual C++ 2013 中,我尝试从“插件”项目导出函数:

void registerFactories(FactoryRegister<BaseShape> & factoryRegister);

它被编译成动态 dll,该动态 dll 将在运行时由“应用程序”项目链接。首先我定义函数指针类型:

    typedef void (*RegisterFactoriesType)(FactoryRegister<BaseShape> &);

用作:

        auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "registerFactories");
        if (!registerFactories) {
            if (verbose) {
                ofLogWarning("ofxPlugin") << "No factories for FactoryRegister<" << typeid(ModuleBaseType).name() << "> found in DLL " << path;
            }
            FreeLibrary(dll);
            return false;
        }

但是,GetProcAddress 返回 NULL。

我可以确认我可以导出 C 函数(使用 extern "C")并使用 GetProcAddress 从同一 DLL 导入它们,但导入 C++ 函数失败。例如这有效:

extern "C" {
    OFXPLUGIN_EXPORT void testFunction(int shout);
}

然后

auto testFunction = (TestFunction)GetProcAddress(dll, "testFunction");
if (testFunction) {
    testFunction(5);
}

所以我的假设是我需要以某种方式考虑为 registerFactories 导出的损坏名称。由于它需要处理 C++ 类型,因此理想情况下我希望在不导出“C”的情况下执行此操作。

这是 dumpbin.exe 看到的内容:

文件 examplePlugin.dll 的转储

文件类型:DLL

Section contains the following exports for examplePlugin.dll

  00000000 characteristics
  558A441E time date stamp Wed Jun 24 14:46:06 2015
      0.00 version
         1 ordinal base
         2 number of functions
         2 number of names

  ordinal hint RVA      name

        1    0 001B54E0 ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z = ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z (void __cdecl registerFactories(class ofxPlugin::FactoryRegister<class BaseShape> &))
        2    1 001B5520 testFunction = testFunction

Summary

     86000 .data
     8E000 .pdata
    220000 .rdata
      E000 .reloc
      1000 .rsrc
    65D000 .text

编辑:

registerFactories 不是赋予 GetProcAddress 的名称。通过手动从 bindump 复制损坏的名称,例如:

        auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "?registerFactories@@YAXPEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z");

它有效!因此,下面的许多答案都与在运行时发现这个损坏的名称有关。

最佳答案

我不会开始寻找损坏的名称。它依赖于编译器(这意味着也依赖于版本),即使它有效,它也将是一个脆弱的解决方案。

我建议以另一种方式获取您的 RegisterFactoriesType 的地址。

假设您的插件中有一个 C 风格的 init 函数(其地址可通过 GetProcAddress 获得),我会这样做:

struct init_data_t
{
   RegisterFactoriesType  factory ;
   ... other members
} ;

然后在 init 内部(所以在 DLL 内部)

void init(init_data_t *data)
{
    init_data->factory = &dll_factory ;
}

基本上,您要求 DLL 提供工厂函数的地址。 dll代码不需要GetProcAddr,可以使用(&)的地址

关于c++ - GetProcAddress 用于将修饰的 C++ 函数导入到 C++ 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31018864/

相关文章:

c++ - 如何挑出发送给仅采用可变参数的宏的第一个参数

c++ - 在无限循环中每 60 秒重置一次变量值

c++ - 从 MATLAB 调用 C++ .dll 库

c# - 如何在 DLL 中包含文档以在 Unity3D 中显示方法摘要?

c++ - 抽象基类成员变量

c++ - 为什么选择默认模板函数比其专用版本更匹配?

Qt部署;程序入口点...无法定位

c# - 导出非托管函数指针时发生访问冲突

c++ - CPU 利用率随时间下降

c++ - 如何从另一个 C++ win32 控制台应用程序调用 C++ Win32 DLL