views:

381

answers:

2

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.

+3  A: 

AFAICT, your codes looks complete and correct, but it's hard to know how you're using it, and from where, and when exactly you get the exception. I think you should provide more information.

One thing I woul d say: you might want to use Pantheios's internal logging "bailout" functionality - a log for the log, I suppose. So, your

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

would be better written as

pantheios::util::onBailOut(pantheios::emergency,
    "Failed to initialise the Pantheios libraries",
    PANTHEIOS_FE_PROCESS_IDENTITY,
    pantheios::getInitErrorString(panres));

That way your log-initialization failure will itself be logged.

dcw
Thanks for the "bailout"-function tips. Good to know.The problem turned out to be non pantheios related. I have provided an answer of my own with the solution I found.
Joakim Karlsson
+1  A: 

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), &amp;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, &quot;w&quot; );
 *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, &quot;r&quot; );
 *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, &quot;w&quot; );
 *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 &lt; 0)
        {
            fprintf(stderr, &quot;Failed to initialise the Pantheios libraries: %s\n&quot;, 
                    pantheios::pantheios_getInitErrorString(panres));

            return FALSE;
        }

        // Set the file name for all back-ends.
        //pantheios_be_file_setFilePath(&quot;output.log&quot;);
    }
    break;
case DLL_THREAD_ATTACH:
    break;
case DLL_THREAD_DETACH:
    break;
case DLL_PROCESS_DETACH:
    pantheios::pantheios_uninit();
    break;
}
return TRUE;
}
Joakim Karlsson
Is it a coincidence that someone named Timo Geusch solved a same/similar problem with pantheios this week with same solution? http://codeblog.bsdninjas.co.uk/index.php?/archives/134-Using-pantheios-to-log-inside-a-C++-JNI-DLL.html. Any suggestions for me, since I use an MFC DLL, which does not have a DllMain but has an InitInstance()? Would the same procedure apply?
ossandcad