views:

95

answers:

5

I'm making a c++ library thats going to be P/Invoked from c#, so i am unable to breakpoint/debug the c++ side of things. So i decided to add logging so i can see if anything goes wrong and where it happens. I add a #define DebugMode 1 in order to determine if i am to log or not. First of all i'm not very good at c++ but i know enough to get around. So my questions are:

  1. Is there a better way than wrapping #if DebugMode #endifs around every Log call? I could simply do that inside the Log method and just return if logging isn't enabled but won't that mean then all those logging strings will be in the assembly?

  2. How can i emulate what printf does with its "..." operator enabling me to pass something like Log("Variable x is {0}", x);

  3. Is there any tricks such as getting the line number or stack trace information of some sort that i can use in the log?

Thanks!

A: 

What about debugging C++ library? In the C++ library Project Properties, Debugging, select C# client in the Command field, and start debugging.

About logging, do you ask about C++ or C# logging? Bot have preprocessor constants defined only in Debug configuration, you can use it.

Alex Farber
c++ logging. I can't see any C# client in that field, only regsvr32 and the ability to Browse
Daniel
Do you know the name of C# executable which calls your C++ Dll? Fill this executavle name in the Command field. If you don't know client name, how do you run it?
Alex Farber
Oh i see, wasn't sure what i was supposed to put in. Thanks!
Daniel
+1  A: 

Check this answer. In that answer was described simple logger with template argument that allows to easily change verbosity level of it.

Kirill V. Lyadvinsky
+1  A: 

One simple way is to just define a macro that does nothing if you're not in debug mode. That way you don't have to wrap every call in an #ifdef.

A simple implementation might be:

#if DebugMode
#define MY_LOG(string, ...) printf(string, __VA_ARGS__)
#else
#define MY_LOG(string, ...)
#endif

There are other ways and libraries (such as boost) but this will get you something quickly.

jeffamaphone
Will this contain all the debugging strings in the assembly? With #if DebugMode Log("something") #endif the strings wouldn't get compiled into the assembly if debugging is disabled? Is this the same for your solution because i like the looks of it
Daniel
The strings will be stripped by the preprocessor if DebugMode is set to 0. You just say `MY_LOG("Something had a value of %d", something);` and you're set. The strings will only be in the debug assembly.
jeffamaphone
Excellent exactly what i wanted!
Daniel
A: 

If the condition is a compile-time constant, so your code (after preprocessing) works out to something like:

if (0) 
    do the logging

Then the compiler will generally be smart enough to strip out the dead code, including the strings that you passed to it (unless you also used the strings in other code that wasn't stripped out, of course).

Code that acts like printf is pretty simple:

#include <stdarg.h>

void log(char const &fmt, ...) { 
    if (do_logging) {
        va_list args;

        va_start(args, fmt);
        vfprintf(output_file, fmt, args);
    }
}

In a macro (it's important that it be in the macro, not the called function) you can use __FILE__ and __LINE__ for the current line number and source file name to put in the log. With the code above, you'd (probably) want to pass those before the format string.

Jerry Coffin
Very helpful thanks! Ah ok i'll just pass those as arguments to the logging method
Daniel
+1  A: 

I recommend using Pantheios, and then you never need to care about DEBUG/!DEBUG. The library uses C++ templates to make sure that no performance cost is paid when logging is not enabled. It's also 100% type-safe and extensible to user defined types.

bar_t  bar;

pantheios::log_DEBUG("foo ", bar, " was doing something you should remember");

Check out their performance page for further information.

dcw
I'll check it out, sounds very cool
Daniel