我想围绕现有的C代码库编写一个C包装器.所以我需要实现一些C-API函数,只是将它们的操作转发到相应的C方法.
我的问题是,我无法弄清楚如何通过现有的类实现前向定义的结构:
//Foo.hpp
namespace myLib {
struct Foo {
//some meaningful C++ body
};
}
//foo.h
//#ifdef __cplusplus etc. left out
extern "C" {
struct myLib_foo;
myLib_foo* mkfoo();
//etc.
}
//foo.cpp
extern "C" {
#include "Foo.hpp"
#include "foo.h"
typedef myLib_foo myLib::Foo; //this does not work
myLib_foo* mkfoo() { return new myLib::Foo(); }
}
在这种情况下,如果我将myLib_foo定义为foo.cpp中的新结构,那么C-API可以并且只能使用指向myLib :: Foo的指针,这显然效果很好.我猜它也有效,如果我在其他地方定义一个结构myLib_foo.然而,由于我想保持我的命名空间可管理,我正在寻找一种方法来定义myLib_foo等同于一些现有(和完全定义)的结构.但这不起作用,因为我的编译器拒绝上面的代码“使用不同类型的typedef重定义”.显然,它区分了类型别名和结构.
有没有办法实现我想要的或C无法实现真正的类型别名?
编辑:
通过下面的答案,我想我可以使用继承加上static_cast:
//foo.cpp
extern "C" {
#include "Foo.hpp"
#include "foo.h"
struct myLib_foo : public myLib::Foo {}; //this does work
myLib_foo* mkfoo() { return static_cast<myLib_foo*>(new myLib::Foo()); }
}
最佳答案 C代码不需要它看到的struct myLib_foo的定义.
它只通过指针和函数来处理它.
在C端,一个简单的实现是一个包含指向它所代表的“真实”对象的指针的结构.然后,您以普通方式(在C代码中)定义它,但当然已经为C代码使用建立了名称.
如果你想避免那种效率低下的问题,那么将实际的对象指针分发给C代码,那么你基本上有两个选择:
> reinterpret_cast,或
> static_cast,将非完全C结构作为(可能为空)基类.
但我会将myLib_foo的简单实现作为一个带有指向真实指针的结构. KISS原则:保持简单,愚蠢*.第二个想法是,为了避免分配和释放问题,并且还避免对编译器的正式依赖(即使这只是学术性的,形式化),我会选择static_cast.考虑到这一切需要什么,这似乎是最简单的.
*:哦,最近几次我在SO上提到了这个原则,那些答案都被严重低估了.当我(正确地)提出宏作为解决方案时,也会发生这种情况.我认为一个人应该在技术上诚实并且忽略一般的SO读者,所以无论如何我都提到它.