我有C ++插件:
$reponse = array(
'csrfName' => $this->security->get_csrf_token_name(),
'csrfHash' => $this->security->get_csrf_hash()
);
echo json_encode($reponse);
这是作为共享库实现的
class PluginBase
{
public:
virtual void foo () = 0;
virtual void bar () = 0;
};
extern "C" PluginBase * new_instance ();
这是通过class PluginImplementation : public PluginBase
{
void foo () override;
void bar () override;
}
void PluginImplementation::foo () {}
// void PluginImplementation::bar () {} // NOTE: MISSING
extern "C" PluginBase * new_instance ()
{
return new PluginImplementation ();
}
使用CMake
构建的:
gcc
即使未实现ADD_LIBRARY (plugin_implementation SHARED PluginImplementation.cpp)
,也可以构建libplugin_implementation.so
。
我知道丢失的符号可能在运行时在程序的其他位置定义,因此链接器允许它从动态库中丢失。
我不要。
除非定义了所有 class 成员,否则是否有办法使PluginImplementation::bar
无法构建?
答案 0 :(得分:2)
我认为您将必须创建具有main
的测试或其他代码,链接到共享库,并尝试实例化相关类。无论如何,这似乎是一个好主意,因为您应该进行单元测试。
答案 1 :(得分:2)
如果目标是现代ELF,并且您不希望通过其名称或其他符号直接引用此类,则可以将可见性设置为“隐藏”:
class __attribute__ ((visibility ("hidden")))
PluginImplementation : public PluginBase
然后,链接器将尝试在本地(在共享库中)解析用于实现虚拟方法的函数的符号,这将导致硬链接器错误(包装起来便于阅读):
plugin.o:(.data.rel.ro.local._ZTV20PluginImplementation
[_ZTV20PluginImplementation]+0x18):
undefined reference to `PluginImplementation::bar()'
/usr/bin/ld: plugin.so: hidden symbol `_ZN20PluginImplementation3barEv'
isn't defined
即使您省略了控制vtable发出的成员函数(以便共享对象不包含带有函数指针的vtable),new_instance
函数也会调用构造函数,该构造函数必须存储vtable指针,并且在隐藏可见性的情况下,也会产生未定义的符号错误。