Open maedoc opened 8 years ago
Is there a reason for having an int return type?
Yes: originally, the macros are just calls to the user-chosen log handler (some printf implementation) which returns int, the number of characters written. The printf implementation was responsible for filling in the format string with its arguments.
This isssue is to avoid calling a printf function by formatting the string with the logging arguments and then passing that string to the user chosen log handler, which means it can be much simpler.
The reason this is useful is that when we use sddekit from Python, for example, we don't want to call libc's printf but actually we want to send our log message to Python's sys.stdout or maybe even use the logging module. As a second example, in MATLAB, if your C code calls printf and not MATLAB's mexPrintf, your message won't even appear in the MATLAB window
Hmm makes sense. If I understood right, the new function definitions should do away with sd_log.c completely and provide a layer of abstraction so that it can be used by python and Matlab. Is that right?
Currently sd_log.c provides way of setting verbose, quiet flags as well as setting the current handler (sd_log_msg
). These will stay. The following changes are required
sd_log_msg_fp
typedef to new handler function pointer type void (*sd_log_msg_fp)(char *)
extern sd_log_msg
declaration](https://github.com/maedoc/sddekit/blob/master/src/sddekit_api.h#L14420sd_log_msg
to sd_log.c
vsnprintf
with its argumentsSo there's a little more to it than just deleting sd_log.c, do you see what I mean?
Yeah there seems to be more to it. Just a tiny(even elementary) doubt. Where would the default handler be present? In sddekit_api or somewhere else?
for completeness I would declare the default handle in api header like
typedef void(*sd_log_handler)(char *);
void sd_log_handler_printf(char*);
then in sd_log.c
static sd_log_handler handler = &sd_log_handler_printf; // hanlder currently in use defaults to printf
void sd_log_handler_printf(char *msg) { printf("%s", msg); }
sd_log_msg(...) {
char msg[2048];
vsnprintf(msg, ...);
(*handler)(msg); // this is calling the static var declared above
}
does this make sense?
Okay I implemented most of the checklist you provided. I'm just a little confused about the getters and setters bit.
the get and set let the user provide a custom handler. In sddekit_api.h
,
typedef void(*sd_log_handler)(char *);
SD_API void
sd_log_set_handler(sd_log_handler);
SD_API sd_log_handler
sd_log_get_handler();
and in sd_log.c
/* handler in use, defaults to printf handler */
static sd_log_handler handler = sd_log_handler_printf;
void sd_log_set_handler(sd_log_handler h)
{
if ((handler = h) == NULL)
sd_err('NULL handler provided');
}
sd_log_handler sd_log_get_handler() { return handler; }
Else where in sd_log.c
, the static handler
instance is called by sd_log_msg
.
Currently logging handlers defined using macros along the lines of
but it would be if
logmsg
where a real function which prints all its args into a string and then passes it off to the designated handler,This should use vsnprintf, c.f.