簡體   English   中英

使用枚舉 class 來自 c++ header 在 c header

[英]Using a enum class from a c++ header in a c header

我正在圍繞 c++ 庫編寫一個 c 包裝器。 在 c++ 中有枚舉類用作 function arguments 的類型。如何在 c header 中正確使用主題。

一種丑陋的方法是在 c function 中使用 int,並將包裝器 function 中的主題轉換為枚舉類型。 但這讓 c function 的用戶不知道有效值,而且很難檢查該值是否有效。

總機 header

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++ function 創建 C 包裝器,為什么不能也為枚舉創建 C 包裝器? 唯一的問題是如何確保兩個枚舉具有相同的值。 您可以在小的代碼更改后檢查它的編譯時間:

cpp header:

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++ 標頭,那么您可以讓預處理器生成枚舉定義; 您需要一組宏用於:

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>

您甚至可以在一個標頭中定義兩個枚舉! 您將為自定義定義更改對__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>

只是為了說明...

生活演示(隱式 C/C++ 檢查變體)。

您不能在 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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM