将前向声明的C-struct定义为C++ - struct

phl*_*psy 8 c c++ forward-declaration

将a 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
Run Code Online (Sandbox Code Playgroud)

然后将其定义为C++ - struct即作为非POD类型?

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

void func(handle_t *h) {
    h->func();
}
Run Code Online (Sandbox Code Playgroud)

一般意图是通过C接口获得外部可访问的opaque类型handle_t,该类型在内部实现为C++数据类型.

Mat*_*son 9

是的,只要C代码永远不需要看到handle_tag结构的"内部" ,并且C++代码执行适当的C++构造/销毁(我预先设定construct并且destruct适用于),这将正常工作.

C代码需要的只是指向某个数据结构的指针 - 它不知道内容是什么,所以内容可以是你喜欢的任何内容,包括构造函数/析构函数依赖数据.

编辑:我应该指出这个或类似于它的方法(例如,使用a void *来记录C部分的对象的地址hold),这是将C代码与C++功能接口的一种相当常见的方式.

Edit2:调用的C++代码不会将异常"泄漏"到C代码中,这一点至关重要.这是未定义的行为,并且非常容易导致崩溃,或者更糟糕的是,"奇怪的事情"不会崩溃...所以除非保证代码不会导致异常(例如std::string,bad_alloc在低的情况下容易抛出)在内存中,需要在C++端使用try/catch像constructanf 这样的代码块func.

  • `struct`,`class`和`union`的名称不是"导出"的.它们在编译期间由编译器使用 - 并用于名称修改,但只要C可调用函数用`extern"C"`包装,这应该无关紧要. (3认同)
  • 你确定有效吗?`api.cpp`的目标文件是否会导出`handle_tag`的非破坏名称? (2认同)