我确实在SO和其他地方环顾四周,但找不到这个相当标准问题的满意答案。我对linux和标准合规性特别感兴趣。我来自以下方法
file plugin.h
图书馆的一部分
#include <memory>
#include <string>
/// defines an interface to be implemented by a plugin
struct PluginBase
{
virtual~PluginBase() {}
virtual double calc(double) const = 0;
};
/// loads a plugin
/// \param[in] file shared object file to load and find plugin in
/// \param[in] strg data for initialising the plugin
std::unique_ptr<PluginBase> load_plugin(std::string const&file, std::string const&strg);
extern "C" {
/// to be implemented with plugin
/// \param[in] strg data for initialising the plugin
std::unique_ptr<PluginBase> create_plugin(std::string const&strg);
}
file plugin.cc
图书馆的一部分
#include "plugin.h"
#include <cassert>
extern "C" {
#include <dlfcn.h> // dlopen() dlsym()
std::unique_ptr<PluginBase>(*create_ptr)(std::string const&);
}
std::unique_ptr<PluginBase> load_plugin(std::string const&file,
std::string const&strg)
{
auto handle = dlopen(file.c_str(),RTLD_LAZY|RTLD_GLOBAL);
assert(handle); // in lieu of proper error handling
auto func_ptr = dlsym(handle,"create_plugin");
assert(func_ptr); // ditto
return reinterpret_cast<create_ptr>(func_ptr)(strg);
}
file some_plugin.cc
不属于图书馆
#include "plugin.h"
struct PluginImpl : PluginBase
{
PluginImpl(std::string const&);
double calc(double) const override;
};
/// has extern "C" linkage
std::unique_ptr<PluginBase> create_plugin(std::string const&strg)
{
return std::unique_ptr<PluginBase>(new PluginImpl(strg));
}
这种做事方式是否正确且符合标准?特别是,我可以从具有std::unique_ptr<>
链接的函数返回extern "C"
吗?并且这样的函数可以采用const引用参数吗?我是否必须将create_ptr
声明为extern "C"
(在文件plugin.cc
中)?我可以避免extern "C"
并直接获取C ++符号(this article讨论这个用于Windows,而不是linux,并且是编译器特定的)?
答案 0 :(得分:2)
Linkage与类型无关。它只是 names 的属性。
C ++标准未指定动态加载方式;具体而言,未指定从void指针到函数指针的重新解释。还有其他一些关于静态初始化器和共享静态对象的细微问题,这些问题没有被正确指定并且会让您大吃一惊。
但是,Posix标准文档<dlfcn.h>
并且还要求强制转换符合您的想法,因此您的代码符合Posix标准,并且应该适用于任何符合Posix的操作系统。
找不到符号名称没有通用的方法。如果您使用C链接,则需要咨询您的平台的C ABI;如果你想使用C ++链接,你需要咨询你的C ++ ABI。既不是通用的也不是固定的,尽管对于C ABI看起来比C ++有更多的跨平台协议。 (具体来说,应该可以在C ABI中以符合源代码名称相同的方式发出符号。)