在共享库中定义抽象类的接口 [英] Defining interface of abstract class in shared library

查看:69
本文介绍了在共享库中定义抽象类的接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个抽象的基类,定义如下:

Say I have a abstract base class defined like so:

interface.hpp

#ifndef INTERFACE_HPP
#define INTERFACE_HPP 1

class interface{
    public:
        virtual void func() = 0;
};

#endif // INTERFACE_HPP

然后,我将翻译单元 test.cpp 编译为共享对象 test.so :

Then I compile a translation unit test.cpp into a shared object test.so:

test.cpp

#include "interface.hpp"
#include <iostream>

class test_interface: public interface{
    public:
        void func(){std::cout << "test_interface::func() called\n";}
};

extern "C"
interface &get_interface(){
    static test_interface test;
    return test;
}

如果我在可执行文件中打开该共享库,然后尝试像这样调用 get_interface :

If I open that shared object in an executable and try to call get_interface like this:

#include <dlfcn.h>
#include "interface.hpp"

int main(){
    void *handle = dlopen("test.so", RTLD_LAZY);
    void *func = dlsym(handle, "get_interface");

    interface &i = reinterpret_cast<interface &(*)()>(func)();
    i.func(); // print "test_interface::func() called"

    dlclose(handle);
}

(只是假装我进行了错误检查)

(just pretend I did error checking)

行为定义是否正确?还是我会假设自己总是可以踩脚趾呢?

请记住,我只会使用clang和gcc

推荐答案

一个陷阱是您希望受保护:〜interface()阻止客户端删除 interface .

One gotcha is that you want protected: ~interface() to discourage clients from deleting interface.

第二个实际问题是,如果您修改 interface ,请记住仅在类的 end 处添加方法,并且不要添加新的虚拟替代项(具有相同名称的功能).(在实践中,即使覆盖项未在头文件中聚集,我也看到了覆盖将它们聚集在一起).

A second, practical issue is that if you modify interface, remember to add the methods at the end of the class only, and do not add new virtual overrides (functions with the same name). (In practice, I have seen overrides be clustered together, even if they are not clustered in the header file).

如果您不仅需要一个接口(例如,您的接口从其他2个接口继承),请使用 virtual 继承.根据我的经验,事实证明添加新的虚拟父母也是有问题的.

If you want more than just a single interface (say, your interface inherits from 2 other interfaces), use virtual inheritance. Adding new virtual parents after the fact has in my experience proved problematic as well.

C ++标准对此均未定义,而C ++标准与二进制接口和代码的运行时无关.但是,以上是我使用类似技术的经验(诚然,使用指针代替引用,并使用MSVC代替gcc/clang).

None of this is defined by the C++ standard, which is agnostic on the subject of binary interfaces and run time loading of code. However, the above is my experience using a similar technique (admittedly, with pointers instead of references, and using MSVC instead of gcc/clang).

您必须跟踪所使用的编译器上的ABI.如果通过这样的接口传递 std 结构,请注意它们有时会更改布局(例如,gcc中的 std :: string 从引用计数变为非引用,或者 std :: list 获得O(1) size ),并且它们在编译器之间的布局兼容性并不是全部兼容(好吧,标准库,不同的编译器倾向于这样做)默认情况下使用其他的.)

You do have to keep track of what the ABI is on the compilers you use. If you pass std structures over such an interface, be aware that they sometimes change layout (std::string in gcc going from reference counted to not, for example, or std::list getting O(1) size), and they are not all that likely to be layout-compatible between compilers (well, standard libraries, which different compilers tend to use different ones by default).

这篇关于在共享库中定义抽象类的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆