将生成的 C++ 结构模板传递到 C 标头

问题描述 投票:0回答:2

另请参阅“如何将 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++ c struct typedef
2个回答
4
投票

问题在于 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 函数,它们的唯一目的是进行转换并调用模板函数。


0
投票

我找到了解决问题的方法,感谢@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); }

© www.soinside.com 2019 - 2024. All rights reserved.