簡體   English   中英

在C ++中使用類型作為枚舉包裝C-API

[英]Wrap C-API with types as enums in C++

目前,我為C-Library編寫了一個C ++ Wrapper,它充當了攝像頭的驅動程序。 可以使用floatboolint屬性設置攝像機。 每個屬性都有一個ID,它是enum PropId成員。 對於每種類型,都有一個屬性信息struct ,一個獲取和設置值的函數:

GetPropertyAttribsI
GetPropertyAttribsB
GetPropertyAttribsF
PropAttribsI
PropAttribsF
PropAttribsB
SetPropertyValueI
SetPropertyValueF
SetPropertyValueB

我現在的問題是我想編寫代碼:

  1. 檢查要設置的屬性值是否在邊界內 ,否則將其設置為默認值。 可以在PropAttribs struct查找邊界和默認值,該PropAttribs struct可以使用相應的GetPropertyAttribs函數進行初始化。
  2. 使用相應的SetPropertyValue(I,B,F) 設置屬性

我可以查找屬性的類型,它位於enum (PROP_TYPE_INT, PROP_TYPE_FLOAT, PROP_TYPE_BOOL)

所以我想要的是一個功能

checkAndSanitizeProperty(T& value, PropId property)

檢查給定屬性是否在邊界內,否則將其設置為默認值。

骨架將是以下,但我不知道如何使用模板參數使它如此通用,它可用於boolfloat而不復制。 設置參數的功能與此非常相似,如果找到任何參數,則應該具有相同的解決方案。

void CameraHandle::checkAndSanitizeProperty(int& value, VRmPropId property, std::string name) {
  VRmPropInfo propInfo;
  VRM_CHECK(VRmUsbCamGetPropertyInfo(device, property, &propInfo));

  if (VRM_PROP_TYPE_INT != propInfo.m_type) {
    ROS_ERROR("Invalid type of property!");
  }

  VRmPropAttribsI attribs;
  VRmUsbCamGetPropertyAttribsI(device, property, &attribs);
  if (value < attribs.m_min || value > attribs.m_max) {
    ROS_WARN("Invalid value for parameter %s, has to be in [%d,%d], but was: %d",
             name.c_str(),
             attribs.m_min,
             attribs.m_max,
             value);

    ROS_WARN("Default will be used for %s: %d", name.c_str(), attribs.m_default);
    value = attribs.m_default;
  }
}

讓我緊張的是,我必須重復很多代碼,所以我尋找一個更清潔的解決方案。 我主要不使用C ++,所以我對模板魔術或C ++習語沒有太多經驗。

宏hackery。

#define CONCAT2( A, B ) A##B
#define CONCAT(A,B) CONCAT2(A,B)

#define MAP_STRUCT( X ) \
  template<class T> struct X; \
  template<class T> using CONCAT(X,_t) = typename X<T>::type; \
  template<> struct X<int> { \
    using type= CONCAT(X, I); \
  }; \
  template<> struct X<float> { \
    using type= CONCAT(X, F); \
  }; \
  template<> struct X<bool> { \
    using type= CONCAT(X, B); \
  };

采用類似VRmPropAttribs的基本結構名稱,並使VRmPropAttribs_t<int>VRmPropAttribsI

#define CALL(X) CONCAT( call_, X )
#define MAP_FUNC_CALL(X) \
  template<class T> \
  struct CALL( X ); \
  template<> struct CALL(X)<int> { \
    template<class...Args> \
    auto operator()(Args&&...args)const \
    -> decltype( CONCAT(X,I)(std::declval<Args>()...) ) { \
      return CONCAT(X,I)(std::forward<Args>(args)...); \
    } \
  }; \

B和F等

 #define MAP_FUNC(X) \
    MAP_FUNC_CALL(X) \
    template<class T, class...Args> \
    auto X(Args&&...args) \
    -> typename std::result_of< CALL(X)(Args...) > \
    { return CALL(X)<T>{}(std::forward<Args>(args)...); }

它定義了一個名為X的函數模板,當傳遞給int ,它使用相同的參數調用XI

現在,這不會處理你的%d格式字符串之類,但你可以做以下事情:

VRmPropAttribs attribs; VRmUsbCamGetPropertyAttribs(設備,財產和屬性); 使用上面的宏后。 一旦你可以做到這一點,你可以用T替換int並使你的方法成為模板方法。

您還需要更好的VRM_PROP_TYPE_INT版本:

template<class T> struct vrm_prop_type{};
template<> struct vrm_prop_type<int>:
  std::integral_constant<int, VRM_PROP_TYPE_INT>
{};

等你可以做到:

vrm_prop_type<T>{} != propInfo.m_type

檢查。

暫無
暫無

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

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