[英]Writing a C++ wrapper for a C library
我有一个以 OO 类型形式编写的遗留 C 库。 典型功能如下:
LIB *lib_new();
void lib_free(LIB *lib);
int lib_add_option(LIB *lib, int flags);
void lib_change_name(LIB *lib, char *name);
我想在我的 C++ 程序中使用这个库,所以我认为需要一个 C++ 包装器。 以上似乎都映射到以下内容:
class LIB
{
public:
LIB();
~LIB();
int add_option(int flags);
void change_name(char *name);
...
};
我以前从未编写过 C++ 包装器,也找不到关于它的太多建议。 这是创建 C++/C 包装器的好/典型/明智的方法吗?
不需要 C++ 包装器 - 您可以简单地从 C++ 代码调用 C 函数。 恕我直言,最好不要包装 C 代码——如果你想把它变成 C++ 代码——很好,但要完全重写。
实际上,假设您的 C 函数是在名为 myfuncs.h 的文件中声明的,那么在您的 C++ 代码中,您将希望像这样包含它们:
extern "C" {
#include "myfuncs.h"
}
为了在使用 C++ 编译器编译时为它们提供 C 链接。
我通常只写一个简单的 RAII 包装器,而不是包装每个成员函数:
class Database: boost::noncopyable {
public:
Database(): handle(db_construct()) {
if (!handle) throw std::runtime_error("...");
}
~Database() { db_destruct(handle); }
operator db_t*() { return handle; }
private:
db_t* handle;
};
使用类型转换运算符,这可以与 C 函数一起使用:
Database db;
db_access(db, ...); // Calling a C function with db's type conversion operator
我认为只有在使库的使用更简单的情况下编写包装器才有意义。 在您的情况下,您不需要传递 LIB*,并且大概可以在堆栈上创建 LIB 对象,所以我会说这是一个改进。
这通常是我将如何处理它。 我也不会使用 char* 而是使用 std::string。
本身不需要 C++ 包装器。 没有什么可以阻止您在代码中调用 C 函数。
我也会考虑将 LIB 重命名为更好的东西,如果没有别的“Lib”
更改名称很可能是一个getter setter ...
所以 GetName(char *) SetName(char *)
然后考虑将其更改为 std::string 而不是 char*,如果它的 SetName(const std::string name) 它将接受一个 char* 作为参数。
即,慢慢转向 C++isms
假设 C 库的分配/释放实例是create_instance和destroy_instance ,并且它公开了一个名为call_function的函数,并且它没有提供用于深度复制实例的 API,这将起作用:
class Wrapper
{
public:
Wrapper(): m_instance(create_instance(), destroy_instance) {}
explicit operator bool() const
{
// null check
return bool(m_instance);
}
void callFunction()
{
call_function(m_instance.get());
}
private:
std::unique_ptr<instance, decltype(&destroy_instance)> m_instance;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.