2015-04-15 153 views
2

我想爲保存緩衝區的OpenGL寫一個簡單的包裝。由於有很多緩衝區,每個緩衝區都有專門的生成和刪除功能,所以我希望能夠使用模板,以便我可以輕鬆創建這些包裝。最終的目標是有這樣的事情:如何將指向GLEW函數的指針傳遞給模板?

gl::VBO v; 
v.gen(); 

我試圖做到以下幾點:

using TBuilder = void(*)(GLsizei, GLuint *); 

template<std::size_t N, TBuilder TConstructor, TBuilder TFreer> 
struct OGLWrapper{ 
    std::array<GLuint, N> data; 
    void gen(){ 
     TConstructor(N, &data[0]); 
    } 
    ~OGLWrapper(){ 
     TFreer(N, &data[0]); 
    } 
}; 

using VBO = OGLWrapper<1, glGenBuffers, glDeleteBuffers>; 

的問題是,glGenBuffersglDeleteBuffers沒有編譯時間常數。它們不可用,直到調用glewInit()。我希望有一種方法可以延遲這些函數的查找,直到VBO生成爲止。在這種情況下完全有可能不能使用模板,但我希望有一種包裝我的OpenGL資源的巧妙方法。


閱讀的答案後,我得到儘可能的:

using TBuilder = decltype(&glGenBuffers); 
using TFreer = decltype(&glDeleteBuffers); 

template<std::size_t N, TBuilder TCons, TFreer TDes> 
struct OGLWrapper{ 
    std::array<GLuint, N> data; 
    OGLWrapper():data{}{} 
    void gen(){ 
     (*TCons)(N, &data[0]); 
    } 
    ~OGLWrapper(){ 
     (*TDes)(N, &data[0]); 
    } 
}; 

using VBO = OGLWrapper<1, &glGenBuffers, &glDeleteBuffers>; 
using VAO = OGLWrapper<1, &glGenVertexArrays, &glDeleteVertexArrays>; 

這是很好的,但我希望刪除TBuilder和TFreer類型定義。我擔心的是泛化,因爲我不確定其他函數是否使用這些簽名。有沒有辦法讓模板推斷出這些類型?

+0

如果沒有編譯時,它不會作爲模板參數工作 - 使用正常(運行時間)參數。 –

+0

有沒有什麼辦法可以使''使用'類​​似,這樣我就不必每次都寫函數參數了? – user975989

回答

1
using TBuilder = void(*)(GLsizei, GLuint *); 

template<std::size_t N, TBuilder* TConstructor, TBuilder* TFreer> 
struct OGLWrapper{ 
    std::array<GLuint, N> data; 
    void gen(){ 
    (*TConstructor)(N, &data[0]); 
    } 
    ~OGLWrapper(){ 
    (*TFreer)(N, &data[0]); 
    } 
}; 

using VBO = OGLWrapper<1, &glGenBuffers, &glDeleteBuffers>; 

活生生的例子

我們儲存指針指向函數指針。函數指針只在您致電glewInit()時更新。所以如果你在那之前使用你的VBO,它會做UB,但你期望什麼?

你可能要注意的一件事是調用約定。但只要你的爲TBuilder準確,你會很好。

最後一個問題是,即使gen未被調用,您的析構函數也會運行。可能你應該在類的構造函數中運行gen?或者如果gen被稱爲bool,則記錄。

+0

對不起,我錯誤的函數指針 - 即將撤消我的編輯。 – orlp

+0

問題是'glGenBuffers'不一定是TBuilder的一種類型。它們被定義爲'#define glGenBuffers GLEW_GET_FUN(__ glewGenBuffers)',它們的內部類型都不相同。例如,'glGenBuffers'是'PFNGLGENBUFFERSPROC','glDeleteBuffers'是'PFNGLDELETEBUFFERSPROC',我不能在指向這些類型和TBuilder的指針之間進行轉換。 – user975989

+0

@ user975989聽起來像一個完全不同於你在OP中描述的問題?根據我對源頭的看法,類型是固定的,但對於這兩種情況是不同的。那麼對於這兩種情況使用不同的類型?問題是他們有時是指針,有時候不是? – Yakk

0

下面是一個使用宏來構造的包裝解決方案,但使用是免費的宏觀:

#define CREATE_GLEW_WRAPPER(name, N, construct, freer) \ 
    struct name {          \ 
     std::array<GLuint, N> data;     \ 
     void gen() {         \ 
      construct(N, &data[0]);     \ 
     }            \ 
                 \ 
     ~name() {          \ 
      freer(N, &data[0]);      \ 
     }            \ 
    };            

namespace gl { 
    CREATE_GLEW_WRAPPER(VBO, 1, glGenBuffers, glDeleteBuffers) 
} 

#undef CREATE_GLEW_WRAPPER