我想围绕现有的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
的指针,这显然效果很好。如果我在其他地方定义struct 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()); }
}
答案 0 :(得分:2)
C代码不需要它所见的struct myLib_foo
的定义。
它只通过指针和函数来处理它。
在C ++方面,一个简单的实现是struct
,它包含指向它所代表的“真实”对象的指针。然后以普通方式(在C ++代码中)定义它,但当然已经为C代码使用建立了名称。
如果你想避免那种效率低下,将实际对象指针分发给C代码,那么你基本上有两个选择:
reinterpret_cast
或
static_cast
将非完全C结构作为(可能为空)基类。
但我会将myLib_foo
的简单实现作为struct
,并指向真实的。{/ del> KISS原则:保持简单,愚蠢 * 。关于第二个想法,为了避免分配和解除分配问题,并且还避免对编译器的正式依赖(即使这只是学术性,形式性),我会选择{{1} }。为了考虑这一切需要什么,这似乎是最简单的。
*:哦,最后几次我在SO上提到了这个原则,那些答案被严重低估了。当我(正确地)提出宏作为解决方案时,也会发生这种情况。我认为一个人应该在技术上诚实而忽略了一般的SO读者群,所以无论如何我都会提到它。