Jac*_*lly 14 c c++ library-design
在准备一个库(让我们称之为libfoo)时,我发现自己面临以下困境:我是否将其编写为带有C包装器的C++库:
namespace Foo {
class Bar {
...
};
}
/* Separate C header. #ifdef __cplusplus omitted for brevity. */
extern "C" {
typedef void *FooBar;
FooBar* foo_bar_new() { return new Foo::Bar; }
void foo_bar_delete(FooBar *bar) { delete bar; }
}
Run Code Online (Sandbox Code Playgroud)
或者将它编写为带有C++包装器的C库更好:
/* foo/bar.h. Again, #ifdef __cplusplus stuff omitted. */
typedef struct {
/* ... */
} FooBar;
void foo_bar_init(FooBar *self) { /* ... */ }
void foo_bar_deinit(FooBar *self) { /* ... */ }
/* foo/bar.hpp */
namespace Foo {
class Bar {
/* ... */
FooBar self;
}
Bar::Bar() {
foo_bar_init(&self);
}
Bar::~Bar() {
foo_bar_deinit(&self);
}
}
Run Code Online (Sandbox Code Playgroud)
你更喜欢哪个?为什么?我赞成后者,因为这意味着我不必担心我的C函数会意外地冒出异常,而且我更喜欢C作为一种语言,因为我觉得它是一个较小的语义雷区.其他人怎么想?
编辑:这么多好的答案.谢谢大家.遗憾的是我只能接受一个.
Art*_*yom 19
小点:
当你编写C库时,它在任何地方都很有用 - 在C中,在C++中(包装器)和许多其他语言,如Python,Java使用绑定等,最重要的是它只需要C运行时.
当你编写C++包装器时,你还需要编写一个C包装器,但它并不像你想象的那么简单,例如:
c_api.h:
extern "C" {
typedef void *Foo;
Foo create_foo();
}
Run Code Online (Sandbox Code Playgroud)
c_api.cpp:
void *create_foo()
{
return new foo::Foo();
}
Run Code Online (Sandbox Code Playgroud)
怎么了?它可能会扔!并且程序将崩溃,因为C没有堆栈展开语义.所以你需要这样的东西:
void *create_foo()
{
try {
return new foo::Foo();
}
catch(...) { return 0; }
}
Run Code Online (Sandbox Code Playgroud)
这适用于每个 C++ api函数.
所以我认为编写C库并提供单独的 C++包装器是更好的解决方案.
此外,它不需要与C++运行时库链接.
使用您喜欢编写库的语言编写库.从技术上讲,您包装的方式并不重要.虽然一些C项目可能旨在排除不是C的库,而C++项目排除用C语言编写的库是很奇怪的,但这主要是一个哲学上的反对而不是实际反对.
在C++包装器中包装C可能会导致稍微更大的包装器,但C程序员更容易接受.
请注意,如果要分发二进制文件,C的简单性是有利的.