在 c header 中使用 c++ header 中的枚举 class
Using a enum class from a c++ header in a c header
我正在围绕 C++ 库编写一个 C 包装器。
在 C++ 中,枚举 类 用作函数参数的类型。
如何在 c header.
中正确使用主题
一种丑陋的方法是在 c 函数中使用 int 并将包装函数中的主题转换为枚举类型。但这让 c 函数的用户对有效值一无所知,而且很难检查该值是否有效。
cppheader
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM
};
void setup(int channel, Directions direction, int initial = -1);
}
c 包装器 header
int setup(int channel, int direction, int initial);
c 封装代码
int setup(int channel, int direction, int initial)
{
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
什么是让 c 函数的用户享受 c++ 库中枚举 类 的好处的好方法。因为它不是我的库,所以我不想对库中的代码进行太多更改。
可以选择将枚举 类 提取到另一个文件并将其包含在原始 header 中。但我不知道如何正确定义它,所以我不必更改cpp库中的命名,仍然可以在c header.
中使用它
您不能在 C 中使用 C++ 代码,因为它不是用通用语言子集编写的。
您可以像这样在 C 包装器中定义相应的枚举,例如:
// C
enum Wrapper_Directions
{
Wrapper_Directions_UNKNOWN,
Wrapper_Directions_OUT,
Wrapper_Directions_IN,
Wrapper_Directions_HARD_PWM,
};
int wrapper_setup(int channel, enum Wrapper_Directions direction, int initial);
你做不到。从 C 代码中使用 C++ 功能是不可能的。您正在为 C++ 函数创建 C 包装器,为什么不能也为枚举创建 C 包装器?唯一的问题是如何确保两个枚举具有相同的值。您可以在小代码更改后检查它的编译时间:
cppheader:
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM,
SIZE
};
}
c 包装器 header:
enum GPIO_Directions
{
GPIO_Directions_UNKNOWN,
GPIO_Directions_OUT,
GPIO_Directions_IN,
GPIO_Directions_HARD_PWM,
GPIO_Directions_SIZE
};
c 包装器代码:
int setup(int channel, GPIO_Direction direction, int initial)
{
static_assert(GPIO::Directions::SIZE == GPIO_Directions_SIZE,
"c wrapper enum must be equal to c++ enum");
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
假设您也可以控制 C++ header,那么您可以让 pre-processor 生成枚举定义;您需要一组宏用于:
genEnumDefine.h:
// DON'T want include guards!
// otherwise including several headers defining enums that way would fail!
#ifdef __cplusplus
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
namespace NAMESPACE \
{ \
enum class NAME \
{ \
CONTENT(NAMESPACE, NAME) \
}; \
}
#define ENUM_ENTRY(N, E, V) V
#else
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
enum NAMESPACE##_##NAME \
{ \
CONTENT(NAMESPACE, NAME) \
};
#define ENUM_ENTRY(N, E, V) ENUM_ENTRY_(N, E, V)
#define ENUM_ENTRY_(N, E, V) N##_##E##_##V
#endif
genEnumUndef.h:
#undef ENUM_DEFINITION
#undef ENUM_ENTRY
#ifndef __cplusplus
#undef ENUM_ENTRY_
#endif
现在您可以简单地定义一个枚举:
#include <genEnumDefine.h>
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
您甚至可以在一个 header 中定义两个枚举!您将为自定义定义更改 __cplusplus
的检查,然后可以执行以下操作:
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
#ifdef __cplusplus
#define GEN_ENUM_CPP 1
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
#undef GEN_ENUM_CPP
#endif
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
仅供说明...
Life demo(隐式 C/C++ 检查变体)。
我正在围绕 C++ 库编写一个 C 包装器。 在 C++ 中,枚举 类 用作函数参数的类型。 如何在 c header.
中正确使用主题一种丑陋的方法是在 c 函数中使用 int 并将包装函数中的主题转换为枚举类型。但这让 c 函数的用户对有效值一无所知,而且很难检查该值是否有效。
cppheader
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM
};
void setup(int channel, Directions direction, int initial = -1);
}
c 包装器 header
int setup(int channel, int direction, int initial);
c 封装代码
int setup(int channel, int direction, int initial)
{
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
什么是让 c 函数的用户享受 c++ 库中枚举 类 的好处的好方法。因为它不是我的库,所以我不想对库中的代码进行太多更改。
可以选择将枚举 类 提取到另一个文件并将其包含在原始 header 中。但我不知道如何正确定义它,所以我不必更改cpp库中的命名,仍然可以在c header.
中使用它您不能在 C 中使用 C++ 代码,因为它不是用通用语言子集编写的。
您可以像这样在 C 包装器中定义相应的枚举,例如:
// C
enum Wrapper_Directions
{
Wrapper_Directions_UNKNOWN,
Wrapper_Directions_OUT,
Wrapper_Directions_IN,
Wrapper_Directions_HARD_PWM,
};
int wrapper_setup(int channel, enum Wrapper_Directions direction, int initial);
你做不到。从 C 代码中使用 C++ 功能是不可能的。您正在为 C++ 函数创建 C 包装器,为什么不能也为枚举创建 C 包装器?唯一的问题是如何确保两个枚举具有相同的值。您可以在小代码更改后检查它的编译时间:
cppheader:
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM,
SIZE
};
}
c 包装器 header:
enum GPIO_Directions
{
GPIO_Directions_UNKNOWN,
GPIO_Directions_OUT,
GPIO_Directions_IN,
GPIO_Directions_HARD_PWM,
GPIO_Directions_SIZE
};
c 包装器代码:
int setup(int channel, GPIO_Direction direction, int initial)
{
static_assert(GPIO::Directions::SIZE == GPIO_Directions_SIZE,
"c wrapper enum must be equal to c++ enum");
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
假设您也可以控制 C++ header,那么您可以让 pre-processor 生成枚举定义;您需要一组宏用于:
genEnumDefine.h:
// DON'T want include guards!
// otherwise including several headers defining enums that way would fail!
#ifdef __cplusplus
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
namespace NAMESPACE \
{ \
enum class NAME \
{ \
CONTENT(NAMESPACE, NAME) \
}; \
}
#define ENUM_ENTRY(N, E, V) V
#else
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
enum NAMESPACE##_##NAME \
{ \
CONTENT(NAMESPACE, NAME) \
};
#define ENUM_ENTRY(N, E, V) ENUM_ENTRY_(N, E, V)
#define ENUM_ENTRY_(N, E, V) N##_##E##_##V
#endif
genEnumUndef.h:
#undef ENUM_DEFINITION
#undef ENUM_ENTRY
#ifndef __cplusplus
#undef ENUM_ENTRY_
#endif
现在您可以简单地定义一个枚举:
#include <genEnumDefine.h>
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
您甚至可以在一个 header 中定义两个枚举!您将为自定义定义更改 __cplusplus
的检查,然后可以执行以下操作:
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
#ifdef __cplusplus
#define GEN_ENUM_CPP 1
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
#undef GEN_ENUM_CPP
#endif
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
仅供说明...
Life demo(隐式 C/C++ 检查变体)。