HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

std::string/std::wstring template wrapper for Win32 API

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stdtemplatewin32wrapperwstringforapistring

Problem

I have not completed this but want to make my own template library for wrapping the Win32 API to make it compatible with std::string/std::wstring... Here's a sample of what I've worked with so far.

My questions are:

  • Is this a good idea?



  • Is it acceptable to undefine Windows API macros (e.g. #undef GetWindowText)?



  • Is there perhaps a better way to do this besides changing the name scheme (e.g. getWindowText or GetWindowString as opposded to GetWindowText)? I prefer not to change the names.



Note: Please don't provide answers like "why don't you just use WTL?" or "just use MFC". I prefer to deal directly with the Windows API; I just want to make it easier to work with std::basic_string.

Implementation

#ifdef _WINUSER_
#undef GetWindowTextLength
template int GetWindowTextLength(HWND hWnd);
template<> int GetWindowTextLength(HWND hWnd) { return ::GetWindowTextLengthW(hWnd); }
template<> int GetWindowTextLength(HWND hWnd) { return ::GetWindowTextLengthA(hWnd); }

#undef GetWindowText
template std::basic_string GetWindowText(HWND hWnd);
template<> std::basic_string GetWindowText(HWND hWnd)
{
    std::size_t len = GetWindowTextLength(hWnd)+1;
    std::vector buffer(len);
    ::GetWindowTextW(hWnd, buffer.data(), len);
    return std::basic_string(buffer.begin(), buffer.end());
}
template<> std::basic_string GetWindowText(HWND hWnd)
{
    std::size_t len = GetWindowTextLength(hWnd)+1;
    std::vector buffer(len);
    ::GetWindowTextA(hWnd, buffer.data(), len);
    return std::basic_string(buffer.begin(), buffer.end());
}
#endif//_WINUSER_


Example Usage

std::basic_string text = GetWindowText(hWnd);

Solution

I have not completed this but want to make my own template library for wrapping the Win32 API to make it compatible with std::string/std::wstring...

Is this a good idea?

If you have the time to do that as an exercise, probably (there should be a lot of effort involved).

If you want to create a library for future use with an intentional name clash, probably no.

Is it acceptable to undefine Windows API macros (e.g. #undef GetWindowText)?

Not really. If you are careful about it, you can make it work, but these macros can change, their implementation can change depending on where MS wants to take their API in the future and what is behind them may change. You are better off writing your library so that there are no name clashes with MS's macro names.

Is there perhaps a better way to do this besides changing the name scheme (e.g. getWindowText or GetWindowString as opposded to GetWindowText)? I prefer not to change the names.

No. You are better off using new names. Seeing the old names in code would make me (as a client of your lib) assume they have the same semantics, parameters and behavior as the WinAPI defines (macros and all). I would assume the names belong to WinAPI and look automatically to MSDN documentation if I had questions (as in, not in your library's documentation).

Using the same name would create confusion for other people using your code, for you as a developer (consider what happens when you have an error due to a macro name accidentally included where you define your API: you'd have errors caused by name clash in macro expansion, when you don't want the macro defined. For you it would be (almost) easy to fix, as you know the problem. Consider what happens though, when a client of your code writes:

#include  // undefines macros and defines your interface
#include   // redefines macros and causes errors


This is an error that is easy to make for client code (especially for someone not familiar with the implementation details/constraints of your library) and it is something that you cannot enforce in your library code (you actually could, if you issue #error directives in your includes but that is as brittle as the whole concept - MS changes some implementation details and you have to update your code).

Also consider that your library would have to be complete from the start - if you only implement wrappers for what you need and discover you need a new API, you'd have to define a wrapper to use it - you will be unable to simply include the WinAPI headers and using it from there (as doing so would cause macro expansion clashes).

I prefer to deal directly with the Windows API; I just want to make it easier to work with std::basic_string.

Nothing is stopping you from wrapping the calls. Just don't undefine WinAPI function access macros and replace them with functions (using undefined macro names). You'd introduce a naming/include limitation in client code that would be hard to get around to in specific cases, and would only work with ugly workarounds in client code or by requiring modifications to your library).

Code Snippets

#include <yourcode.h> // undefines macros and defines your interface
#include <windows.h>  // redefines macros and causes errors

Context

StackExchange Code Review Q#25581, answer score: 4

Revisions (0)

No revisions yet.