为C++库创建自动C包装器
Create automatic C wrapper for C++ library?
假设我有一个C++DLL。AFAIK,C++没有广泛采用的ABI标准,因此,为了确保它能够工作,并且不依赖于目标应用程序的编译器,我需要将我的库封装在C接口中。
有什么工具可以自动生成这样的界面吗?如果他们能在C接口周围生成包装器,看起来像是原始的C++对象,例如,那也会很好
Foo* f = new Foo(); // FooWrapper* fw = Foo_create();
f->bar("test"); // Foo_bar(fw, "test")
转换为在我的库中使用生成的C ABI调用的C函数。我知道C++是一种相当复杂的语言,并不是所有的东西都可以很容易地封装在C接口中,但我想知道是否有这样的解决方案可以支持C++语言的一个子集(也许可以借助一些手动编写的IDL/XML文件)?
目前还没有广泛采用的针对C++的ABI标准
我敢肯定这有点夸张——任何给定的平台都没有那么多不同的编译器,所以为每个供应商生成一个DLL可能会更容易(例如,微软、Windows上的GCC、Linux上的GCC,Solaris的Sun和GCC,MacOS的GCC——据我所知,CLANG与GCC兼容)。
添加C层接口基本上意味着接口层不能:1.使用任何需要特殊复制/分配/构造行为的对象。2.使用任何"抛出"异常。3.使用虚拟功能。通过该接口。
我认为,解决"缺乏ABI"造成的问题比制作一个适合C++使用的中间有C接口更容易。
如果您想让C++代码可以从其他编译器/标准库中调用,可以使用https://github.com/jbandela/cppcomponents.完全披露-我是图书馆的作者。
下面是一个简单的hello-world示例
首先制作一个名为library.h的文件在该文件中,您将定义组件
#include <cppcomponents/cppcomponents.hpp>
struct IPerson
:public cppcomponents::define_interface<cppcomponents::uuid<0xc618fd04,0xaa62,0x46e0,0xaeb8,0x6605eb4a1e64>>
{
std::string SayHello();
CPPCOMPONENTS_CONSTRUCT(IPerson,SayHello);
};
inline std::string PersonId(){return "library!Person";}
typedef cppcomponents::runtime_class<PersonId,cppcomponents::object_interfaces<IPerson>> Person_t;
typedef cppcomponents::use_runtime_class<Person_t> Person;
下一个创建库.cpp在这个文件中,您将实现接口和组件
#include "library.h"
struct PersonImplementation:cppcomponents::implement_runtime_class<PersonImplementation,Person_t>
{
std::string SayHello(){return "Hello Worldn";}
};
CPPCOMPONENTS_DEFINE_FACTORY(PersonImplementation);
最后是使用实现的主程序(称之为example1.cpp)
#include "library.h"
#include <iostream>
int main(){
Person p;
std::cout << p.SayHello();
}
要构建该程序,您需要下载cppcomponents(只需从上面的git链接进行克隆)。它是一个只有头的库,只需要一个c++11编译器。
以下是如何在Windows 上构建它
cl /EHsc example1.cpp /I pathtocppcomponents
g++ -std=c++11 library.cpp -o library.dll -shared -I pathtocppcomponents
其中pathocppcomponents是cppcomponents的目录。我假设你的路径上有cl和g++。
要运行该程序,请确保library.dll与example1.exe位于同一目录中,然后运行example1.exe
这个库需要相当兼容的c++11支持,因此它需要MSVC 2013预览版,以及至少g++4.7。此库可在Windows和Linux上运行。
据我所知,答案是否定的,您应该通过一点"黑客攻击"和修改自行处理,例如,您的t
变量(即std::string
)可能会被t.c_str()
"外部化"到C接口,因为c_str
返回一个const char *
,这是C完全可以理解的类型。
我个人并不觉得C++很复杂,我也看不出"ABI问题",我的意思是没有什么是完美的,但你正在将你的整个代码库外部化到C来"解决"这个问题?只要首先使用C,而且C也不是一种容易处理的语言,例如,在C中甚至没有"字符串"的概念,在C++中解决一些琐碎的问题,同时确保所有类型的安全,如果你想达到同样的目标,那么在C中真的很有挑战性。
我认为你在这方面做得有点太过分了,而且你正在使事情复杂化,因为现在你在最流行的平台上有3+1的主要选项:
- libsupc++
- libcxxrt
- libc++abi
- 再加上ABI是否适用于您选择的MSVC(又名"只有上帝知道")
对我来说,在linux上,libsupc++运行得很好,我正在关注libc++abi项目,我也没有看到任何大问题,唯一真正的问题是llvm目前基本上是一个面向苹果的项目,所以对其他平台没有真正好的支持,但是libc++abi在linux上也能很好地编译和工作(尽管它基本上毫无用处,毫无意义,但在linux上已经有了libsupc++)
我也永远不会在Windows下使用MSVC,在我看来,最好使用类似GCC的编译器,比如mingw,你有出血的边缘功能,你可以大大简化你的代码库和构建阶段。
- 如何在c++17中制作一个模板包装器/装饰器
- std::vector的包装器,使数组的结构看起来像结构的数组
- 如何在c++迭代器类型中包装std::chrono
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- 用pybind11包装C++抽象类时出错
- 为左值和右值的包装器实现C++范围
- C结构,其指针将被包装在unique_ptr中
- 如何包装第三方DLL在R中使用
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 将 N-arg 函数包装到另一个函数中
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 包装一个对象并假装它是一个 int
- 使用 Python Extension API 包装复杂C++类
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 包装C++类时不完整的类型 GLFWwindow
- 将函数包装器转换为 std::function
- C++函数包装器来捕获某些信号
- 创建包装升压适配器的自定义范围类
- 如何包装(撰写)增强 hana 地图并访问括号运算符(运算符 [])?
- 使用运算符*重载包装矩阵乘法