1

I was looking at this github logger project and I was trying it in my own environment. I tried to change the function log_log to static so it could not be called in a different file, and would force "users" (me) to only use the macros.

When I change the function to static, I get undefined reference in main, even though the macro should be able to see it. Why is this? And is there a way to accomplish this?

#include <stdio.h>
#include <stdarg.h>

#define LOG_VERSION "0.1.0"

typedef void (*log_LockFn)(void *udata, int lock);

enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };

#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

void log_set_udata(void *udata);
void log_set_lock(log_LockFn fn);
void log_set_fp(FILE *fp);
void log_set_level(int level);
void log_set_quiet(int enable);

void log_log(int level, const char *file, int line, const char *fmt, ...);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user2840470
  • 919
  • 1
  • 11
  • 23
  • 1
    C macros just perform textual substitution. If a macro expansion references a static function, then that static function must be defined in the same file as the macro reference. – Tom Karzes Feb 03 '19 at 17:15

3 Answers3

3

You get the 'undefined reference' linker error because the log_log function is not defined in the header; it is merely declared. (See Understanding the difference between definining and declaring a variable; the concepts are similar for declaring and defining functions.)

By saying that the function is static, you're saying that log_log() will be defined in the source file where your main() function is defined, and it will also be separately defined in any other file that tries to call it (which would be wasteful unless the function is trivial). But the definition isn't there — so you get the 'undefined reference' message when linking the program. Using my default compiler options, I'd also be told by the compiler (not the linker) that a function declared as a static function is not defined.

You can't do what you tried without going through contortions such as including the source file — not the header but the source file — that defines log_log in the code that contains your main() function. However, you really don't want to do that; you really, really, really don't want to do it.

Let laziness protect you: it's much harder to type log_log(CS_POTATOES, "codswallop", -366, "abuse is rampant") than log_trace("abuse is rampant"), so people are unlikely to do it. And you can always search for and replace direct calls to log_log, serving appropriate warnings on any members of your team inclined to abuse it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

The preprocessor doesn't understand anything about C. All the preprocessor does is substitute any instances of the log_*** macros with calls to log_log. Only once the preprocessor has finished making these substitutions, does the compiler step in to read the code, which has been modified by the preprocessor.

The compiler does not care nor know that these calls to log_log were put in by the preprocessor. All it sees is a reference to a function that you're not supposed to use because you have declared it static, so it emits an error.

lost_in_the_source
  • 10,998
  • 9
  • 46
  • 75
1

Why cant a macro use static function

Macros don't use any function. They just expand to source code, or fragments thereof. Source code generated that way can include function calls, but it has exactly the same semantics as if it appeared literally in the file instead of having come from expansion of a macro.

In particular, if a macro appearing in a given file expands to code containing a function call, then either the called function must be external or a definition of it must appear in the same source file as the call.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157