我正在尝试从 DLL 调用函数。该 DLL 的 API 如下所示:

#pragma once

#include <stdint.h>
#include <stdbool.h>

#if defined _MSC_VER || defined __MINGW32__
    #ifdef __cplusplus
        #define API extern "C" __declspec(dllexport)
    #else
        #define API __declspec(dllexport)
    #endif
#else
    #ifdef __cplusplus
        #define API extern "C" __attribute__((visibility("default")))
    #else
        #define API __attribute__((visibility("default")))
    #endif
#endif


API void* construct(const char* initString);

我正在使用 boost 加载该函数调用,然后尝试调用它:

#include <boost/dll/import.hpp>
#include <boost/function.hpp>
#include <boost/filesystem.hpp>
#include <iostream>


typedef void* (ConstructT)(const char*);

int main() {
    boost::function<ConstructT> constructFunc = boost::dll::import_alias<ConstructT>(
        "TestPluginDll.dll",
        "construct",
        boost::dll::load_mode::append_decorations | boost::dll::load_mode::load_with_altered_search_path
    );
    
    std::string initArg = "hello";
    void* pluginInstance = constructFunc(initArg.c_str());
    std::cout << pluginInstance << std::endl;
}

但是,调用时失败constructFunc,并在以下代码中引发错误boost/dll/import.hpp

        // Compilation error at this point means that imported function
        // was called with unmatching parameters.
        //
        // Example:
        // auto f = dll::import_symbol<void(int)>("function", "lib.so");
        // f("Hello");  // error: invalid conversion from 'const char*' to 'int'
        // f(1, 2);     // error: too many arguments to function
        // f();         // error: too few arguments to function
        template <class... Args>
        inline auto operator()(Args&&... args) const
            -> decltype( (*f_)(static_cast<Args&&>(args)...) )
        {
            return (*f_)(static_cast<Args&&>(args)...);
        }

为什么会失败? 的类型std::string.c_str()const char*,因此看起来它是正确的类型。

作为参考,我的 DLL 代码如下所示:

#include <plugin_interface.hpp>
#include <iostream>
#include <nlohmann/json.hpp>


class MyPlugin {
public:
    MyPlugin() {}
};


extern "C" API void* construct(const char* initString) {
    MyPlugin* plugin = new MyPlugin();
    return static_cast<void*>(plugin);
}

例外情况:

Exception has occurred: W32/0xC0000005
Unhandled exception at 0x00007FF77B713633 in tmp.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

14

  • @user7860670 没有构建错误消息,错误发生在运行时,它只是退出程序而不输出任何内容,当我在调试模式下运行它时,它只是在那部分代码上中断


    – 

  • 2
    如果发生崩溃那不是编译错误。它发生在代码的哪个位置所有相关变量的值是什么?您是否进行过任何错误检查以确保 DLL 和函数正确加载和获取?


    – 


  • 1
    正确吗dllPath?它是相对路径吗?并且 DLL 不在您所期望的位置?如果您使用完整的绝对路径,那么它会起作用吗?


    – 

  • 1
    抛出错误哪个错误?您只显示了错误发生的位置,没有显示错误的内容。


    – 

  • 2
    请发布一个。显示的 main.cpp 没有 17 行代码。确保应用程序绑定使用显示的代码构建的实际 .dll。您似乎在 Windows 上使用 mingw。然后检查已加载的 C++ 运行时。


    – 



最佳答案
2

经过进一步调查,我意识到 boost 实际上是按预期工作的。问题是由 的错误使用引起的boost::dll::import_alias。它应该只与通过BOOST_DLL_ALIAS宏从库中导出的特殊符号一起使用。alias在此上下文中是全局命名空间中的一个变量,其纯名称包含指向实际导出的深层嵌套函数的指针。请参阅

#include <boost/dll/alias.hpp> // for BOOST_DLL_ALIAS   
#include "../tutorial_common/my_plugin_api.hpp"

namespace my_namespace {

class my_plugin_aggregator : public my_plugin_api {
    float aggr_;
    my_plugin_aggregator() : aggr_(0) {}

public:
    std::string name() const {
        return "aggregator";
    }

    float calculate(float x, float y) {
        aggr_ += x + y;
        return aggr_;
    }

    // Factory method
    static boost::shared_ptr<my_plugin_aggregator> create() {
        return boost::shared_ptr<my_plugin_aggregator>(
            new my_plugin_aggregator()
        );
    }
};


BOOST_DLL_ALIAS(
    my_namespace::my_plugin_aggregator::create, // <-- this function is exported with...
    create_plugin                               // <-- ...this alias name
)

} // namespace my_namespace

由于construct它只是全局命名空间中的常规函数​​,因此可以使用boost::dll::import_symbol

boost::function<ConstructT> constructFunc = boost::dll::import_symbol<ConstructT>(
        "TestPluginDll.dll",
        "construct",
        boost::dll::load_mode::append_decorations | boost::dll::load_mode::load_with_altered_search_path
    );

1

  • 感谢更新,我BOOST_DLL_ALIAS之前用的是,但我不得不改用与 C 兼容的 API,而且我不知道我必须改用 import_symbol


    – 

除了@user7860670指出的错误限制之外,这个typedef是不正确的:

typedef void* (ConstructT)(const char*);

它需要一个extern "C"

extern "C" {
  typedef void* (ConstructT)(const char*);
}

虽然在实践中,省略语言链接可能在许多工具链上起作用,但在形式上,它