调用使用 boost import_alias 加载的 DLL 函数时出现访问冲突异常

问题描述 投票:0回答:1

我正在尝试从 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.

Exception thrown

c++ boost dll
1个回答
0
投票

我已成功重现此问题并决定进行调查。事实证明,该问题是 boost.dll 中的一个错误。

import_alias
dll.get
重载提供了错误的类型,导致其执行无效的转换并返回垃圾值而不是对导入函数的引用。

boost/dll/import.hpp

如果

T
这里是
ConstructT

template <class T>
BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::dll::fs::path& lib, const char* name,
    load_mode::type mode = load_mode::default_mode)
{
    typedef typename boost::dll::detail::import_type<T>::base_type type;

    boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode);
    return type(p, p->get<T *>(name));
}

boost/dll/shared_library.hpp

然后

T
这里是
ConstructT *
导致
aggressive_ptr_cast
转换为指针到指针,造成混乱。

//! \overload T& get(const std::string& symbol_name) const
template <typename T>
inline typename boost::disable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T&>::type get(const char* symbol_name) const {
    return *boost::dll::detail::aggressive_ptr_cast<T*>(
       get_void(symbol_name)
    );
}

快速修复相当简单

return type(p, p->get<T>(name));
。更突出的解决方案是正确检查提供的类型对于
get
过载是否有意义。看起来应该带有函数指针的指针丢失了。

必须更新Boost库。

© www.soinside.com 2019 - 2024. All rights reserved.