C++ 如何从C+;中的dll实例化类+;?

C++ 如何从C+;中的dll实例化类+;?,c++,dll,dllimport,C++,Dll,Dllimport,我正在为插件开发人员编写一个API,以便他们可以通过我的API访问应用程序的SDK。My API在头文件中提供了宏和抽象类*,插件开发人员必须包含该头文件才能从抽象基类继承并实现必要的函数(*参见下面的代码) 就目前这个问题的研究而言,我已经阅读了许多MSDN和stackoverflow文章,发现这些文章最相关: 还有大量类似标题的文章询问如何从DLL调用函数 这个问题是关于获取继承的抽象类/接口的实例,您希望插件开发人员在创建.dll文件时实现该类/接口 也许我的方法是不正确的,我陷

我正在为插件开发人员编写一个API,以便他们可以通过我的API访问应用程序的SDK。My API在头文件中提供了宏和抽象类*,插件开发人员必须包含该头文件才能从抽象基类继承并实现必要的函数(*参见下面的代码)

就目前这个问题的研究而言,我已经阅读了许多MSDN和stackoverflow文章,发现这些文章最相关:

  • 还有大量类似标题的文章询问如何从DLL调用函数
这个问题是关于获取继承的抽象类/接口的实例,您希望插件开发人员在创建
.dll
文件时实现该类/接口

也许我的方法是不正确的,我陷入了困境,但像反射和/或COM之类的东西似乎是我应该做的。。。由于应用程序将在客户端运行,因此对于此操作而言,只有COM似乎有些过分。这篇关于的文章似乎很有希望,但我正在Visual Studio中使用C++17

在最高级别,预期行为是:

  • API.dll
    加载插件目录(例如
    plugin/plugin1.dll
    plugin/plugin2.dll
  • API.dll
    通过抽象类“
    getPlugin()
  • 调用插件实现的其他方法,值得注意的是
    load()
  • 下面是一些关于插件开发人员使用API的背景设置信息。API为开发人员提供了接口/抽象类的头以及在宏中创建单例的方法

    API:baseplugin.hpp

    typedef uintptr_t(*pFunc)();
    HINSTANCE hinstLib = LoadLibrary(TEXT("plugin1.dll"));
    if (hinstLib != NULL) {
        FARPROC ProcAdd = GetProcAddress(hinstLib, "getPlugin"); // address to singeleton function
        // If the function address is valid, call the function.  
        if (NULL != ProcAdd) {
            pFunc pPluginSingleton = (pFunc) ProcAdd;
            baseplugin* plugin1Singleton = (baseplugin*) pPluginSingleton(); // THIS LINE WORKS, I GET A POINTER TO A SINGLETON
            plugin1Singleton->load(); // THIS CRASHES!!!! 
    
    #ifdef BUILDINGAPI
    #定义插件导入
    #定义PLUGINEXPORT\uuu declspec(dllimport)
    #否则
    #定义PLUGINIMPORT\uuu declspec(dllimport)
    #定义PLUGINEXPORT\uuu declspec(dllexport)
    #恩迪夫
    //此处定义的用于创建/删除单例的长宏
    #定义插件(类类型)\
    静态std::共享单例\
    外部“C”{\
    PLUGINEXPORT-uintpttr_t getPlugin()\
    {                                                               \
    如果(!singleton){\
    singleton=std::shared_ptr(new classType())\
    }                                                           \
    返回reinterpret_cast(&singleton)\
    }                                                               \
    PLUGINEXPORT void erasePlugin(){\
    if(单件)\
    singleton=nullptr\
    }                                                             \
    }
    //此处定义的抽象类:
    类PluginPortBasePlugin
    {
    公众:
    虚空荷载()=0;
    虚空卸载()=0;
    };
    
    因此,插件开发人员可以使用以下方法快速创建插件:

    插件:plugin1.hpp

    typedef uintptr_t(*pFunc)();
    HINSTANCE hinstLib = LoadLibrary(TEXT("plugin1.dll"));
    if (hinstLib != NULL) {
        FARPROC ProcAdd = GetProcAddress(hinstLib, "getPlugin"); // address to singeleton function
        // If the function address is valid, call the function.  
        if (NULL != ProcAdd) {
            pFunc pPluginSingleton = (pFunc) ProcAdd;
            baseplugin* plugin1Singleton = (baseplugin*) pPluginSingleton(); // THIS LINE WORKS, I GET A POINTER TO A SINGLETON
            plugin1Singleton->load(); // THIS CRASHES!!!! 
    
    插件:plugin1.cpp

    typedef uintptr_t(*pFunc)();
    HINSTANCE hinstLib = LoadLibrary(TEXT("plugin1.dll"));
    if (hinstLib != NULL) {
        FARPROC ProcAdd = GetProcAddress(hinstLib, "getPlugin"); // address to singeleton function
        // If the function address is valid, call the function.  
        if (NULL != ProcAdd) {
            pFunc pPluginSingleton = (pFunc) ProcAdd;
            baseplugin* plugin1Singleton = (baseplugin*) pPluginSingleton(); // THIS LINE WORKS, I GET A POINTER TO A SINGLETON
            plugin1Singleton->load(); // THIS CRASHES!!!! 
    
    现在我只剩下加载编码/构建
    API.dll
    来加载plugin.dll目录。以下是我目前的代码,我意识到如果不了解RTTI,这是行不通的:

    API:dllmain.cpp

    typedef uintptr_t(*pFunc)();
    HINSTANCE hinstLib = LoadLibrary(TEXT("plugin1.dll"));
    if (hinstLib != NULL) {
        FARPROC ProcAdd = GetProcAddress(hinstLib, "getPlugin"); // address to singeleton function
        // If the function address is valid, call the function.  
        if (NULL != ProcAdd) {
            pFunc pPluginSingleton = (pFunc) ProcAdd;
            baseplugin* plugin1Singleton = (baseplugin*) pPluginSingleton(); // THIS LINE WORKS, I GET A POINTER TO A SINGLETON
            plugin1Singleton->load(); // THIS CRASHES!!!! 
    
    这里可能值得注意的是,使用
    plugin1.dll
    的代码构建
    API.dll
    ,工作正常。我现在正在测试/弄清楚如何在运行时加载插件类型。我已经验证了我能够通过调试器获取指向singleton的指针,但是在将load方法强制转换为抽象类后,我在尝试运行load方法时崩溃:
    0xc000005:访问冲突执行位置0x80B1CCDC

    您的应用程序对插件中定义的具体类型一无所知。它只能对应用程序中定义的类进行操作。每个插件都需要提供一个工厂方法,用于创建插件中定义的具体类型的实例,并返回指向应用程序中定义的抽象类的指针。类似于在
    Plugin1.dll
    中定义的内容:

    baseplugin* PLUGINEXPORT create_plugin()
    {
        return new plugin1;
    }
    

    在应用程序中,您可以动态加载
    Plugin1.dll
    ,获取
    create\u plugin
    函数的地址,并调用它来获取
    Plugin1
    类的实例,作为指向
    baseplugin
    抽象类的指针。

    实现插件API的一个好方法是借助。它为实现插件机制提供了一些有用的工具。例如,.

    这不是我的宏所做的吗?我意识到我在宏的原始问题中有一个输入错误,
    DLLIMPORT
    应该是
    pluginport
    ,我现在就编辑它。在这两种情况下,
    plugin1.cpp
    中的宏
    PLUGIN(plugin1)
    定义了
    getPlugin()
    ,它将指向单个实例的指针返回为
    uintptpr\t
    。在最后一段代码中,我尝试将其转换为baseplugin*并使用它——但这会使应用程序崩溃,请参见:
    pluginSingleton->load()结果证明我为API实现的插件架构是正确的。真正的问题是我对plugin1的load()函数的调用。我接受这个答案,因为它提供了boost::dll作为参考,以表明我确实正确地使用了接口,并消除了任何疑问。不过我要说的是,没有必要重新诠释演员阵容。