I originally published this post on my old blog in 2009. I’ve edited it a little for readability but left the contents unchanged, so it may be out of date and not reflect the current state of the pantheios library. I also haven’t been using pantheios for logging since about 2010, and have been using Boost.Log instead.

I recently had to come up with a logging solution for C++ code a JNI DLL/shared library that is providing the data translation layer between Java and underlying native C and C++ libraries. As usual, some logging was required to aid fault-finding in a production environment, if necessary. A quick survey of the state of C++ logging showed that not a lot had changed since I last looked at logging libraries. In fact, a lot of them seem to have survived unchanged for several years. I’m not sure if that is a good thing and a sign of maturity or a sign of “making do” and the low priority most projects assign to a performant logging library. Eventually I settled on pantheios as it offered several features that were crucial for this application. The major one was that pantheios it is extremely modular and will only link in the parts you really need. I consider this a major advantage over the more monolithic libraries that pull in all their functionality all the time, especially when you link them in as a static library (yes, log4cxx, I’m looking at you). Linking in the logging library as a static library was necessary to avoid conflicts with other libraries that are being used in the same process.

Initial tests in a simple command line program suggested that worked well and matched the requirements. Unfortunately I couldn’t get it to log at all inside the JNI DLL, so I ended up trawling Google’s search results for quite a while and experimented quite a lot of different settings until I ended up with a working combination.

First, pantheios initialises itself automatically if you use it inside a regular executable. For various reasons, it can’t do that inside a Windows DLL, so you have to do that explicitly. Fortunately, Matthew Wilson, the author of pantheios, had explained on a mailing list how to do this. Typically, I can’t find the post anymore so here’s the code that I’m using to initialise the library, which is more or less a verbatim copy of Matthew’s code minus a couple of lines that weren’t required:

#include <iostream>

#include <pantheios/pantheios.hpp>
#include <pantheios/inserters.hpp> 
#include <pantheios/frontends/stock.h>

const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "JNITestDll.1";

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  dwReason,
                       LPVOID lpReserved
                                         )
{
  if (dwReason == DLL_PROCESS_ATTACH)
  {
    if (pantheios::pantheios_init() < 0)
    {
      std::cout << "Failed to initialise the Pantheios logging libraries!n" << std::endl;
      return FALSE;
    }
    else
    {
      pantheios::log_INFORMATIONAL("Logger enabled!");
    }
  }
  else if (dwReason == DLL_PROCESS_DETACH)
  {
    pantheios::log_INFORMATIONAL("Logger disabled!");
    pantheios::pantheios_uninit();
  }
  return TRUE;  // ok
}

This seemed to initialise the library correctly. I wasn’t getting any error messages to prove otherwise but unfortunately I still wasn’t getting any output either. Yes, I could see that pantheios_init() returned a value that indicated successful initialisation, the logging functions were called and the output went straight into the bit bucket somewhere.

It took me a little while to work out what happened but in the end I tracked it down to something that I filed under “JNI oddity”. Pantheios supports implicit linking for both its frontends (the part that you interact with) and its backends which are responsible for sending the output somewhere. Being the usual lazy so-and-so programmer, I had borrowed one of the implicit link files from the samples. Which should have worked OK as it was for a command line executable, but didn’t.

After some poking and prodding I realised that the issue was that by default, in this particular implicit link file pantheios would use the Windows Console logger when the code was built Windows. This didn’t work (probably because this was in a DLL and there wasn’t a console associated with it. Switching to the fprintf backend fixed this issue and I was finally seeing logging output from the JNI DLL. Here is the code for the implicit linking:

/* Pantheios Header Files */
#include <pantheios/implicit_link/core.h>
#include <pantheios/implicit_link/fe.simple.h>
#include <platformstl/platformstl.h>
#include <pantheios/implicit_link/be.fprintf.h>

#if (   defined(UNIX) || 
        defined(unix))&& 
    (   defined(_WIN32) || 
        defined(_WIN64))
# include <unixem/implicit_link.h>
#endif /* _WIN32 || _WIN64 */

All in all I’m happy with Pantheios as a logging solution. If you’re looking for a versatile C++ logger, I’d recommend you look at it.

Note from 2014: In a project that is not using or cannot use Boost, I would still look at pantheios first before looking at other libraries.

Leave a Reply