c++dllloggingpantheios

Use Pantheios logging framework from a dll


Im a trying to use pantheios logging framework from inside a c++ dll. I have successfully built the dll and it executes through my test application (C++ MFC Application).

I have used implicit linking with the following includes:

#include <pantheios/implicit_link/core.h>
#include <pantheios/implicit_link/fe.simple.h>
#include <pantheios/implicit_link/be.console.h>

My DllMain initializes pantheios with the following calls:

extern "C" const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "FinishingLineController";

BOOL APIENTRY DllMain( HMODULE hModule,
                   DWORD  ul_reason_for_call,
                   LPVOID lpReserved)
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            {
            int panres =  pantheios::pantheios_init(); 

            if(panres < 0)
            {
                fprintf(stderr, "Failed to initialise the Pantheios libraries: %s\n", 
                        pantheios::pantheios_getInitErrorString(panres));

                return FALSE;
            }
            }
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        case DLL_PROCESS_DETACH:
            pantheios::pantheios_uninit();
            break;
        }
        return TRUE;
    }

When I execute the following code I get an

Microsoft C++ exception: stlsoft::winstl_project::windows_exception at memory location 0x0013da84

pantheios::log_DEBUG("Test logging");

I have tried to use explicit linking instead without any result.


Solution

  • Some further tests showed that the logging from the dll works if I link it to a console application instead of a windows application. And if I change the backend to "file" instead of "console" the windows application do log correctly to the file. So the problem seem to be that the windows application doesn't have a "console".

    The solution was to redirect standard output/input pipes to a new console. This has to be done for a win32 application since a console is not created by default.

    void RedirectIOToConsole()
    {
        int hConHandle;
        long lStdHandle;
        CONSOLE_SCREEN_BUFFER_INFO coninfo;
        FILE *fp;
    
        // allocate a console for this app
        AllocConsole();
    
        // set the screen buffer to be big enough to let us scroll text
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
        coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    
        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
    
        // redirect unbuffered STDOUT to the console
        lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
        hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
        fp = _fdopen( hConHandle, "w" );
        *stdout = *fp;
        setvbuf( stdout, NULL, _IONBF, 0 );
    
        // redirect unbuffered STDIN to the console
        lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
        hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
        fp = _fdopen( hConHandle, "r" );
        *stdin = *fp;
        setvbuf( stdin, NULL, _IONBF, 0 );
    
        // redirect unbuffered STDERR to the console
        lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
        hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
        fp = _fdopen( hConHandle, "w" );
        *stderr = *fp;
        setvbuf( stderr, NULL, _IONBF, 0 );
    
        // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
        // point to console as well
        std::ios::sync_with_stdio();
    }
    

    And then call this function from DllMain.

    BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        {
            RedirectIOToConsole();
    
            int panres =  pantheios::pantheios_init();  
    
            if(panres < 0)
            {
                fprintf(stderr, "Failed to initialise the Pantheios libraries: %s\n", 
                        pantheios::pantheios_getInitErrorString(panres));
    
                return FALSE;
            }
    
            // Set the file name for all back-ends.
            //pantheios_be_file_setFilePath("output.log");
        }
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        pantheios::pantheios_uninit();
        break;
    }
    return TRUE;
    }