C++ 将正向声明的C-struct定义为C++-结构

C++ 将正向声明的C-struct定义为C++-结构,c++,c,forward-declaration,C++,C,Forward Declaration,将struct转发声明为C-struct // api.h #ifdef __cplusplus extern "C" { #endif typedef struct handle_tag handle_t; handle_t *construct(); void destruct(handle_t *h); void func(handle_t *h); #ifdef __cplusplus } #endif 然后将其定义为C++-结构,即非POD类型

struct
转发声明为C-
struct

// api.h
#ifdef __cplusplus
extern "C" {
#endif

    typedef struct handle_tag handle_t;

    handle_t *construct();
    void destruct(handle_t *h);

    void func(handle_t *h);

#ifdef __cplusplus
}
#endif
然后将其定义为C++-
结构
,即非POD类型

// api.cpp
struct handle_tag {
    void func();
    std::string member;
};

void func(handle_t *h) {
    h->func();
}

一般的意图是通过C接口获得一个外部访问的不透明类型<代码> HooLeYT,它内部实现为C++数据类型。

< P>是的,只要C代码不需要看到“内部”的“代码”> HANDLYTAG/<代码>结构,那么它就可以正常工作,适当的C++构造/破坏是由C++代码执行的(我以前是在<代码>构造< /COD>和<代码>破坏< /代码> for)。p> C代码所需要的只是一个指向某个数据结构的指针——它不知道内容是什么,因此内容可以是任何您喜欢的内容,包括依赖于构造函数/析构函数的数据

编辑: 我要指出的是,这是一个非常常见的方式,将C代码与C++功能相连接。p> 编辑2:
关键的是,C++代码调用并不会将异常“泄漏”到C代码中。这是未定义的行为,很容易导致崩溃,或者更糟的是,不会崩溃的“奇怪的事情”。。。因此,除非代码保证不引起异常(例如,代码> STD::String 容易抛出<代码> BADOL OLC/<代码>内存不足,所以在C++侧使用“<代码>尝试/catch”/COD>块内部代码,如<代码>构造>代码> ANF<代码> FUNC< /代码>。p> 不会像现在这样工作,但是这个概念还可以。定义函数时,还需要确保名称没有损坏,以便C代码能够找到它们。这意味着应该在api.cpp文件的顶部添加
#include“api.h”

你确定这样行吗?
api.cpp
的对象文件是否会为
handle\u tag
导出一个未损坏的名称?@KonradRudolph:通常只有变量和函数会显示为已导出的名称,只是类型本身没有任何损坏的名称。只要将导出的typedef仅用作指针,就不会有问题。C不需要知道结构的大小就可以知道指向该结构的指针的大小。
struct
class
union
的名称不“导出”。编译器在编译过程中使用它们,并用于名称篡改,但只要C可调用函数用
extern“C”
包装,这就不重要了。@Plasmah肯定是这样的。从什么时候开始,C ABI支持模板和名称空间?但是我同意,没有理由在全局名称空间中损坏非模板类型。但这是普遍保证的吗?顺便说一下,Poess与C和C++的链接无关。C++名称不管它们是否是荚都被损坏。POD@B嗯,是的,没有人声称它是,不是?命名诡辩:“句柄”是一种给你一种间接的方式来指代某事物的东西,类似于指针。将重载结构命名为“handle\t”,然后要求用户使用指向它的指针是没有意义的。相反,为结构赋予一些其他名称,并将typedef“handle\u t”作为指向它的指针。然后直接使用该类型,而不是指针。我的观点是,类型
handle\t*
在我看来非常不自然,我可能会不断地、无意识地使用plain
handle\t
,然后在它不编译时感到恼火。比较
句柄
和Windows API中的类似类型。