[英]Wrap C-API with types as enums in C++
目前,我為C-Library編寫了一個C ++ Wrapper,它充當了攝像頭的驅動程序。 可以使用float
, bool
或int
屬性設置攝像機。 每個屬性都有一個ID,它是enum PropId
成員。 對於每種類型,都有一個屬性信息struct
,一個獲取和設置值的函數:
GetPropertyAttribsI
GetPropertyAttribsB
GetPropertyAttribsF
PropAttribsI
PropAttribsF
PropAttribsB
SetPropertyValueI
SetPropertyValueF
SetPropertyValueB
我現在的問題是我想編寫代碼:
PropAttribs struct
查找邊界和默認值,該PropAttribs struct
可以使用相應的GetPropertyAttribs
函數進行初始化。 SetPropertyValue(I,B,F)
設置屬性 我可以查找屬性的類型,它位於enum (PROP_TYPE_INT, PROP_TYPE_FLOAT, PROP_TYPE_BOOL)
。
所以我想要的是一個功能 :
checkAndSanitizeProperty(T& value, PropId property)
檢查給定屬性是否在邊界內,否則將其設置為默認值。
骨架將是以下,但我不知道如何使用模板參數使它如此通用,它可用於bool
和float
而不復制。 設置參數的功能與此非常相似,如果找到任何參數,則應該具有相同的解決方案。
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.