在定義C++, C通用介面函式時讓C++介面支援預設引數

啟程軟體發表於2022-04-09

在SOUI4的開發中,所有SOUI核心物件都採用了一種類似COM介面的技術來匯出介面。

這所以採用這種方案,主要目的是為了讓SOUI4支援C語言呼叫,擴充套件SOUI的使用場景。

眾所周知,C++函式的引數支援配置預設值,但C函式是不支援預設值的。

比如定義了類似下面一個介面

1 #undef INTERFACE
2 #define INTERFACE IRenderTarget
3 DECLARE_INTERFACE_(IRenderTarget, IObjRef)
4 {
5 //...
6     STDMETHOD_(HRESULT, SelectObject)
7     (THIS_ IRenderObj * pObj, IRenderObj * *ppOldObj) PURE;
8 //...
9 };

IRenderTarget::SelectObject方法的功能是給當前的RenderTarget選擇一個繪圖物件,同時如果ppOldObj不為NULL,則通過ppOldObj返回當前正在使用的同型別繪圖物件。

很多時候使用者並不關心原來的物件,所以通常給它置為NULL即可。這也是SOUI3及之前版本的預設引數。

由於4.0中,該介面可能是在C++中引用,也可能是在C中引用,如果還是直接使用C++的方法給它設定預設引數NULL,在C中引用就會導致編譯失敗。

是由於這個方法是控制元件自繪中常用的方法,為了減少升級SOUI3的程式碼到SOUI4的難度,我一直在想有沒有辦法能夠相容兩種語言的特性。

今天無意中想起來可以用一個簡單的巨集解決。

於是我定義了下面的巨集:

1 #ifdef __cplusplus
2 #define DEF_VAL(x) =x
3 #else
4 #define DEF_VAL(x)
5 #endif//__cplusplus

有了這個巨集,我們就可以同時相容C++和C語言了,上面的介面修改如下:

1 #undef INTERFACE
2 #define INTERFACE IRenderTarget
3 DECLARE_INTERFACE_(IRenderTarget, IObjRef)
4 {
5 //...
6     STDMETHOD_(HRESULT, SelectObject)
7     (THIS_ IRenderObj * pObj, IRenderObj * *ppOldObj DEF_VAL(NULL)) PURE;
8 //...
9 };

通過這樣修改,經過測試,可以解決我的問題。

相關文章