Sunday, February 8, 2015

DIY: Bind OpenGL(WGL) APIs using std::regex

Windows SDK doesn't provides direct way to access modern OpenGL APIs. So, as you know developers suffer to choose the method to acquire huge amount of address of WGL APIs. (or just decide using GLEW)

The popular DIY option is parsing the Khronos Group's extension header files with script languages and generate C++ glue code. But, I didn't. A good news is std::regex is now available on Visual Studio 2013, So I felt it's the simplest option to do.

struct GLFunc
{
GLFunc(){}
GLFunc(const GLFunc& r) {
*this = r;
}
const GLFunc& operator=(const GLFunc& r) {
name = r.name;
decl = r.decl;
caster = r.caster;
return *this;
}
std::string name;
std::string decl;
std::string caster;
};
std::vector<GLFunc> glFuncs;
void ParseHeader(const char* healderFileName, const char* regExp, const char* conventions)
{
char* h = (char*)LoadFile(healderFileName);
std::string str = h;
std::regex pattern(regExp);
auto funcBegin = std::sregex_iterator(str.begin(), str.end(), pattern);
auto End = std::sregex_iterator();
int dist = std::distance(funcBegin, End);
printf("%d functions found in %s\n", dist, healderFileName);
int i = 0;
for (auto it = funcBegin; it != End; it++) {
std::smatch m = *it;
if (m.size() < 4) {
continue;
}
GLFunc func;
func.name = m[2].str();
func.decl = m[1].str() + "(" + conventions + "*" + m[2].str() + ")" + m[3].str();
func.caster = m[1].str() + "(" + conventions + "*)" + m[3].str();
glFuncs.push_back(func);
printf("\r%d/%d", ++i, dist);
}
printf("\n");
free(h);
}
int _tmain(int argc, _TCHAR* argv[])
{
ParseHeader("glheaders/glcorearb.h", "^GLAPI\\s+([\\w\\s\\*]+)APIENTRY\\s+(gl\\w+)\\s*(\\(.*\\))", "APIENTRY");
ParseHeader("glheaders/wglext.h", "^(\\w+(?:\\s+\\w+)*\\s+)WINAPI\\s+(wgl\\w+)\\s*(\\(.*\\))", "WINAPI");
return 0;
}
view raw wgl_grabber.cpp hosted with ❤ by GitHub
Tools are always getting better and better! Isn't it?:)

std::sregex_iterator looks wired from the perspective of STL programmers, but it is the way for multiple match of OpenGL API declaration in the header files.(std::regex_match is only for single match, it wasn't for me) and std::smatch contains divided parts of a declaration, such as name of API, return type and parameters.

My project files are available on GitHub.

No comments:

Post a Comment