BR Fink
BR Fink

Reputation: 29

Variable name to string in function call, C++

I'm expanding our internal debugging library, and I've run into an odd wall. I'd like to output a variable name as a string. From elsewhere on this site, I found that a macro can be used to do this within a file:

#define VarToStr(v) #v
...
printf("%s\n", VarToStr(MatName));

This outputs MatName. But now let's try this through a function across files (Matrix is a defined type):

// DebugHelpers.h
#define VarToStr(v) #v
...
void PrintMatrix(const Matrix &InputMat)
{
    printf("%s\n", VarToStr(InputMat));
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName);
}

This outputs InputMat, instead of MatName. How can a function in another file get the variable name from the calling file?

While more complex solutions (wrapper classes, etc.) would be useful for the larger community, my implementation needs to minimize impact to preexisting code/classes.


Update:

Inspired by zenith's comments, I implemented both of his proposed solutions for comparison's sake and got both working quickly. The macro works well for simple outputs, while the function allows for more complex work (and type checking/overloading). I hadn't known that preprocessor macros could be so complex. I'll remember both for future use. Thanks !

Upvotes: 2

Views: 675

Answers (3)

In general you cannot do that (getting the name of a variable at runtime, from e.g. its address or in C++ its reference).

I am focusing on Linux:

However, on Linux (and GNU glibc based systems), for global variables (and functions), you might use the GNU specific dladdr(3) function.

If all the relevant code was compiled with -g (to get debug info), you might parse the debug information in DWARF format (perhaps also using __builtin_frame_address, etc.). With some pain, you might be able to get the name of some local variables from its address on the call stack. This would be a significant effort (probably months of work). Ian Taylor's libbacktrace (inside GCC) might be useful as a starting point.

You could also start (assuming everything is compiled with -g), with e.g. popen(3), a gdb -p debugging process.

Notice that recent GDB debugger is scriptable in Python or Guile, so practically speaking developing Python or Guile functions for GDB would be quicker.

You could also simply add debug output like here.

Upvotes: 1

Emil Laine
Emil Laine

Reputation: 42828

As mentioned by others, C++ doesn't support runtime reflection, so if you want to have a string whose contents will only be known at runtime (which is when the call to PrintMatrix will happen), you need to pass it as an argument.

And because you always know what your variables' names are you don't need the VarToStr macro:

// DebugHelpers.h
void PrintMatrix(const Matrix &InputMat, const char* MatName)
{
    printf("%s\n", MatName);
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName, "MatName");
}

But there's another choice: make PrintMatrix a macro itself, since it's only a debug thing anyway:

// DebugHelpers.h
#define PRINT_MATRIX(InputMat)\
printf(#InputMat "\n");\
... // output InputMat contents


// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PRINT_MATRIX(MatName);
}

Now after preprocessing, AnalysisSubProgram342 will look like this:

void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    printf("MatName\n");
    ... // output InputMat contents
}

Upvotes: 4

Bathsheba
Bathsheba

Reputation: 234655

You can't. Neither C nor C++ retain variable names at runtime.

All your macros are doing is substituting text which happens at compile time.

Upvotes: 10

Related Questions