|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionAs well as providing a C++ API, the 1: InitialisationUse of the #include <pantheios/pantheios.h>
#include <stdio.h>
#include <stdlib.h>
extern const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "pantheios-C";
int main(int argc, char** argv)
{
int panres = pantheios_init();
if(panres < 0)
{
fprintf(stderr, "Failed to initialise the Pantheios libraries: %s\n",
pantheios_getInitErrorString(panres));
return EXIT_FAILURE;
}
else
{
/* . . . rest of program */
pantheios_uninit();
return EXIT_SUCCESS;
}
}
The requirement for explicit initialisation is in contrast to the C++ API. where initialisation is automatic upon inclusion of pantheios/pantheios.hpp. (If your link unit contains one or more C++ compilation units that include pantheios/pantheios.hpp, and your link unit is not a DLL, and you've not defined 2: Using the C APIThe Pantheios C API is based on the The main logging function in the API is PANTHEIOS_CALL(int) pantheios_logprintf(pan_sev_t severity
, char const* format
, ...);
Syntactically, the specification of format strings and arguments is identical to int i = 10;
double d = 9.9;
pantheios_logprintf(PANTHEIOS_SEV_NOTICE, "i=%d, d=%G", i, d);
The only differences are that There are two other functions in the PANTHEIOS_CALL(int) pantheios_logvprintf( pan_sev_t severity
, char const* format
, va_list args);
PANTHEIOS_CALL(void) pantheios_logputs( pan_sev_t severity
, char const* message);
The former takes an array of arguments in the same way as does 3: Argument TypesThe second consequence of the It also means that the C API is not type-safe. Passing an integer to 4: Logging Custom TypesUnlike the C++ API, there is no assistance available in the C API for the logging of custom types. Consider the following example, where an IPv4 address argument is logged on entry to a function: int connect_to_peer(struct in_addr const* addr)
{
pantheios_logprintf(PANTHEIOS_SEV_DEBUG
, "connect_to_peer(%u.%u.%u.%u)"
, (NULL == addr) ? 0 : ((addr->s_addr & 0x000000ff) >> 0)
, (NULL == addr) ? 0 : ((addr->s_addr & 0x0000ff00) >> 8)
, (NULL == addr) ? 0 : ((addr->s_addr & 0x00ff0000) >> 16)
, (NULL == addr) ? 0 : ((addr->s_addr & 0xff000000) >> 24));
. . .
This is a lot of heavy boilerplate, and must be repeated (carefully) in each place an int connect_to_peer(struct in_addr const* addr)
{
pantheios::log_DEBUG("connect_to_peer(", addr, ")");
. . .
An alternative approach for C, which offers greater robustness and transparency of the application code, is to use a helper converter function, as in: char const* convert_addr(char* buff, size_t cchBuff, struct in_addr const* addr);
int connect_to_peer(struct in_addr const* addr)
{
char buff[16]; /* space enough for IPv4 */
pantheios_logprintf(PANTHEIOS_SEV_DEBUG
, "connect_to_peer(%s)"
, convert_addr(&buff[0], STLSOFT_NUM_ELEMENTS(buff), addr));
. . .
The downside is that the conversion always takes place, regardless of whether logging at the Debug level is currently enabled or not. With the previous explicit form, no conversion is undertaken until after the severity level is checked. The downloadable project contains implementations of both these approaches, along with the main program, to illustrate the differences between them. SummaryWe've seen how to use the We've seen that when logging custom types with the C API, you are forced to make compromises between efficiency and reuse and expressiveness. With the C++ API no such compromises are necessary - it is 100% type-safe and only ever performs conversions when they're going to be used. Naturally, the advice from the That's a brief introduction to using There's a whole lot more to the world of Please feel free to post questions on the forums on the Pantheios project site on SourceForge. History
|
||||||||||||||||||||||