为dlopen()加载的类自动创建包装器 [英] Automatically Creating Wrappers for Classes Loaded with dlopen()

查看:41
本文介绍了为dlopen()加载的类自动创建包装器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个代理类,该代理类使用 dlopen()加载共享库,并将其成员函数转发到幕后加载的共享对象内部的代理类实例的相应成员./p>

例如,共享库有一个 Person 类:

  class Person{...无效setName(std :: string name);}; 

我添加了一个包装文件,其中包含 person.h 头并定义了以下符号:

 外部"C" {void Person_setName(void * instancePointer,std :: string name);} 

此调用只转发给个人对象,它是第一个参数 extern"C" ,以避免整个名称更改问题.在客户端,我编写了一个 Person 类,该类具有相同的成员,该成员持有指向包装好的类的指针并转发所有调用.

现在出现一些问题:

  1. 是否有更好的方法从加载的共享对象实例化和使用类?我发现了其他一些无需包装即可使用的解决方案,但是在Usenet上不建议使用它,并且高度依赖GCC及其版本和未定义的行为,因此我决定采用这种方法.
  2. 有没有一种方法可以自动创建这些包装器?它们都只是添加了第一个参数,该参数是每个方法的实例并转发到真实对象的指针.为此必须有一些模板魔术,不是吗?目前,我正在使用一些宏来完成这项工作,但我会对模板解决方案感兴趣.
  3. 也许有些工具可以自动执行此类操作,例如 SWIG ?据我所知, SWIG 仅用于将C ++接口导出为高级语言.

解决方案

是否有更好的方法从加载的共享对象中实例化和使用类?

如果您想安全并支持任何共享库(即通过任何编译器/标志等进行编译),则否:您必须通过C ABI.

请记住,您也不应该在接口中使用C ++对象,例如就像您要传入 Person_setName std :: string .

有没有一种方法可以自动创建这些包装器?为此必须有一些模板魔术,不是吗?目前,我正在使用一些宏来完成这项工作,但我会对模板解决方案感兴趣.

否,您不能即时创建成员函数(我们还没有反射,元类和类似的编译时功能).

它们都只是添加了第一个参数,该参数是每个方法的实例的指针,并指向真实的事物.

您当然可以创建一个可变参数模板,该模板将参数转发到给定的 extern"C" 函数,但是与简单地调用C函数相比,您并没有得到什么有用的东西.换句话说,不要这样做:要么创建一个适当的C ++类,要么让用户调用C函数.

也许有像SWIG这样的工具可以自动执行此操作?据我所知,SWIG仅用于将C ++接口导出为高级语言.

我过去曾使用 Clang的工具支持来执行与预构建步骤,所以确实有可能!

I'm writing a proxy class that loads a shared library with dlopen() and forwards its member functions to the appropriate members of the proxied class instance inside the loaded shared object behind the scenes.

For example, the shared object has a Person class:

class Person
{
    ...
    void setName(std::string name);
};

I've added a wrapper file that includes the person.h header and defines the following symbol:

extern "C" {
    void Person_setName(void* instancePointer, std::string name);
}

This call just forwards to the person object which is the first argument, extern "C" to avoid the whole name mangling issue. On the client side I've written a Person class with the same members that holds a pointer to the wrapped class and forwards all calls.

Now some question arise:

  1. is there a better way to instantiate and use a class from a loaded shared object? I've found some other solution that can live without the wrappers, but it's discouraged on Usenet and highly dependent on GCC and its version, and undefined behavior, so I decided against that route.
  2. is there a way to automate the creation of those wrappers? They are all just adding a first argument that is a pointer to an instance to each method and forward to the real thing. There has to be some template magic for that, no? Currently I'm using some macros for the job but I'd be interested in a template solution.
  3. Maybe there is some tool that can do such a thing automatically, like SWIG? As far as I've seen SWIG is just for exporting a C++ interface to high level languages.

解决方案

is there a better way to instantiate and use a class from a loaded shared object?

If you want to be safe and support any shared object (i.e. compiled by any compiler/flags etc.), then no: you have to go through the C ABI.

Remember you should not use C++ objects in the interface either, e.g. like the std::string you are passing in Person_setName.

is there a way to automate the creation of those wrappers? There has to be some template magic for that, no? Currently I'm using some macros for the job but I'd be interested in a template solution.

No, you cannot create member functions on the fly (we do not have reflection, metaclasses and similar compile-time features yet).

They are all just adding a first argument that is a pointer to an instance to each method and forward to the real thing.

You can create a variadic template that forwards arguments to a given extern "C" function, of course, but you are not really getting anything useful from that compared to simply calling the C functions. In other words, don't do that: either create a proper C++ class or leave the users to call the C functions.

Maybe there is some tool that can do such a thing automatically, like SWIG? As far as I've seen SWIG is just for exporting a C++ interface to high level languages.

I have used Clang's tooling support in the past to perform similar tasks as a pre-build step, so it is indeed possible!

这篇关于为dlopen()加载的类自动创建包装器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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