cwindowsgccmingwc-header

Is there a way to make a header file, like stdio.h and not include it in the compiler?


I'm trying to make a library and I've found that I need to make a header file, which I did and I have a C file too, which contains the functions.

wprintf.h:

#ifdef WPRINTF
#include <wchar.h>
void _working_wprintf(wchar_t *wstr);
#define wprintf(x) _working_wprintf(x)
#endif

wprintf.c:

#include <windows.h>
#include <wchar.h>

void _working_wprintf(wchar_t *wstr) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD written;
    if (!WriteConsoleW(hConsole, wstr, wcslen(wstr), &written, NULL)) {
        wprintf(L"Error\n");
    }
}

The point of this is to override the wprintf function with a working version (the default wprintf isn't working as it should)

Is there a way to make using this easy, like stdio.h, so this works too:

main.c:

#include <wprintf.h>  // or "wprintf.h"

int main() {
    wprintf(L"állat");  // means "animal" in Hungarian
    
    return 0;
}

Then

gcc main.c -o main.exe

Right now I need to use this if I want it to compile:

gcc main.c wprintf.c -o main.exe -DWPRINTF

And I need to add: #include "wprintf.h"

Instead of: #include <wprintf.h>


Solution

  • If the intent is to distribute this and this alone as a development time utility, I see no reason why you can't make it a single-header library:

    /**
     * wprintf.h
     */
    
    #include <windows.h>
    #include <stdio.h>
    #include <wchar.h>
    
    #ifndef WPRINTF_H
    #define WPRINTF_H
    
    static inline void _wprintf_impl(wchar_t *wstr) {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD written;
        if (!WriteConsoleW(hConsole, wstr, wcslen(wstr), &written, NULL)) {
            fwprintf(stderr, L"Error\n");
        }
    }
    
    /**
     * Placeholder documentation
     * @param s A null-terminated wide character string
     */
    #define wprintf(s) _wprintf_impl(s)
    
    #endif
    

    Or, if you prefer not to inline, you can use an implementation macro. This is done in other popular single-file libraries like stb_image, and can be done here like so:

    /**
     * wprintf.h
     */
    
    #include <wchar.h>
    
    #ifndef WPRINTF_H
    #define WPRINTF_H
    
    // Stub
    void _wprintf_impl(wchar_t *wstr);
    
    /**
     * Placeholder documentation
     * @param s A null-terminated wide character string
     */
    #define wprintf(s) _wprintf_impl(s)
    
    #endif
    #ifdef WPRINTF_IMPLEMENTATION
    #ifndef WPRINTF_IMPLEMENTATION_ONCE
    #define WPRINTF_IMPLEMENTATION_ONCE
    #include <windows.h>
    #include <stdio.h>
    
    // Implementation
    void _wprintf_impl(wchar_t *wstr) {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD written;
        if (!WriteConsoleW(hConsole, wstr, wcslen(wstr), &written, NULL)) {
            fwprintf(stderr, L"Error\n");
        }
    }
    
    #endif
    #endif
    

    Single-header libraries are somewhat contoversial, but I find it easy to justify for something so small.