另请参阅“如何将 C++ 类的对象传递给 C 函数或从 C 函数传递?” (C++ FAQ),但是我不确定如何将其应用到我的案例中。
我正在尝试从我的 C++ 源文件中公开 C 兼容类型(结构)。
我通过将结构“转换”为不同的方式来使它们在理论上兼容。如何使这些“强制转换”类型可以通过 C 标头访问
c_header.h
?
cpp_header.hpp
#ifdef __cplusplus
template <typename T>
struct item {
uint32_t foo;
T data;
};
int bar(struct item<T> *item);
extern "C" {
typedef struct item<uint8_t> u8_item_t;
typedef struct item<uint16_t> u16_item_t;
}
#endif // __cplusplus
c_header.h
#include "cpp_header.hpp"
int bar_u8(u8_item_t *item);
int bar_u16(u16_item_t *item);
cpp_source.cpp
#include "cpp_header.hpp"
#include "c_header.h"
template <typename T>
int bar(struct item<T> *item) {
// ...
return 0;
}
extern "C" {
int bar_u8(u8_item_t *item) { return bar<uint8_t>(item); }
int bar_u16(u16_item_t *item) { return bar<uint16_t>(item); }
}
编译时,我看到的第一个错误是
c_header.h : error: unknown type name 'u8_item_t'
| int bar_u8(u8_item_t *item);
^~~~~~~~~
c_header.h : error: unknown type name 'u16_item_t'
| int bar_u16(u16_item_t *item);
^~~~~~~~~
问题在于 C 类型的 typedef 位于 C++ 保护范围内。不幸的是,如果你把它们移到外面,你在编译 C 的任何时候都会得到一个错误,因为 C 没有模板类型。
也许你最好的选择就是定义 C 不完整类型。您还需要为您使用的模板类型的每个变体提供一个单独的 C 函数,因为 C 无法区分它们 - 它们都是指针,而且也没有参数重载。
#ifdef __cplusplus
template <typename T>
struct item {
uint32_t foo;
T data;
};
int bar(struct item<T> *item);
extern "C" {
#endif
typedef struct u8_item_t u8_item_t;
typedef struct u16_item_t u16_item_t;
int bar_u8(u8_item_t *item);
int bar_u16(u16_item_t *item);
#ifdef __cplusplus
}
#endif // __cplusplus
bar_u8
和 bar_u16
是 shim 函数,它们的唯一目的是进行转换并调用模板函数。
我找到了解决问题的方法,感谢@PasserBy 和@ÖöTiib 的反馈
我开始将 C++ 和 C 代码混合到一个可以包含在 C 或 C++ 中的头文件中。我很想知道这是否是一个好主意(我显然是 C++ 方面的新手 ^^)
c(pp)_header.h
#ifdef __cplusplus
template <typename T>
struct item {
uint32_t foo;
T data;
};
typedef item<uint8_t> u8_item_t;
typedef item<uint16_t> u16_item_t;
#else // __cplusplus
// Opaque definitons for C
typedef struct u8_item u8_item_t;
typedef struct u16_item u16_item_t;
#endif // __cplusplus
#ifdef __cplusplus
template <typename T>
int bar(item<T> *item){
// ...
return 0;
}
extern "C" {
#endif // __cplusplus
int bar_u8(u8_item_t *item);
int bar_u16(u16_item_t *item);
#ifdef __cplusplus
}
#endif
我不知道模板对于多文件使用的限制。这意味着我必须将所有声明放在
.hpp
中,将 C 实现放在 .cpp
中
cpp_source.cpp
#include "c(pp)_header.h"
int bar_u8(u8_item_t *item) { return bar<uint8_t>(item); }
int bar_u16(u16_item_t *item) { return bar<uint16_t>(item); }