See also "How can I pass an object of a C++ class to/from a C function?" (C++ FAQ), however I am unsure how to apply it to my case.
I'm trying to expose C-compatible types (structs) from my C++ source file.
I made them theoretically compatible by "casting" the struct to different ways. How do I make those "casted" types accessible to by C header 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); }
}
When compiling, the first errors I see are
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);
^~~~~~~~~
The problem is that your typedefs for the C types are inside the C++ guard. Unfortunately, if you move them outside, you will get an error any time your are compiling C, because C does not have template types.
Probably your best choice is just to define C incomplete types. You will also need a separate C function for each variant of your template type you use because C can't tell the difference -they are all pointers and it also doesn't have parameter overloading.
#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
and bar_u16
are shim functions and their only purpose is to do the cast and call the template function.