tags:

views:

94

answers:

2

Hello,

gcc 4.4.2 c89

I re-engineering some code in c89. However, I am totally confused with the code that uses the following #defines. So I created a small application that maybe I would understand more of how this is working.

From what I can gather the MODULE_API will pass a function name and call the macro MODULE_SOURCE_API and concatenate name and func. So I create a simple function called print_name and ran the code. I got the following error messages:

implicit declaration of function ‘print_name’
undefined reference to `print_name'

What would be the main reason for doing this?

#include <stdio.h>

#define MODULE_SOURCE_API(name, func) name##_##func
#define MODULE_API(func) MODULE_SOURCE_API(mod_print, func)

void MODULE_API(print_name)(const char const *name);

int main(void)
{
    printf("=== Start program ===\n");

    print_name("Joe bloggs");

    printf("== End of program ===\n");

    return 0;
}

void MODULE_API(print_name)(const char const *name)
{
    printf("My name is [ %s ]\n", name);

}

Many thanks for any advice,

EDIT ==== I have just made a correction I should be calling

MODULE_API(print_name)("Joe Bloggs");

But how can I print out what will be the outcome of concatenating? And what is the reason for doing this?

Many thanks,

+4  A: 

You can try to manually expand the macros to understand what is going on:

void MODULE_API( print_name )( const char * name ); // the second const there is redundant
                 // maybe you meant 'const char * const??

=(expand MODULE_API)=>

void MODULE_SOURCE_API( mod_print, print_name )( const char* name );

=(expand MODULE_SOURCE_API)=>

void mod_print_print_name( const char *);

As you see, the function being declared (and defined at the end of the code) is not print_name, but rather mod_print_print_name. Go back to the initial code and see how the macro is intended to be used. I would assume that function calls are performed with the same macros that are used for declarations and definitions.

David Rodríguez - dribeas
I don't think the second `const` is actually redundant. `const char* const name`, as I understand, means it's a `const` pointer to a `const char`.
Sapph
I am thinking I am getting the general idea. At pre-compile time the pre-compiler will replace all function names with the concatenated names. There are many of these in the source code. But isn't there a better way to do this, then using 2 macro functions?
robUK
@Sapph: in the original code: `const char const *`, both `const` refer to the `char`, and none to the actual pointer. As you said, if the second const was on the right of the pointer then it would make sense. I have not checked it, but it might even be a compilation error having the `const` on both sides of the `char` type.
David Rodríguez - dribeas
Sorry about that, apparently when I contribute to SO at 5 in the morning I can't see where asterisks are placed.
Sapph
You are correct. It should have been (const char * const name)
robUK
+6  A: 
#define MODULE_SOURCE_API(name, func) name##_##func
#define MODULE_API(func) MODULE_SOURCE_API(mod_print, func)

 void MODULE_API(print_name)(const char const *name);

That will be producing a function named mod_print_print_name instead of print_name

You can check it on gcc with the -E option.

gcc -E ak.c gives

/* ...... */
void mod_print_print_name(const char const *name);

int main(void)
{
   printf("=== Start program ===\n");

   print_name("Joe bloggs");

   printf("== End of program ===\n");

   return 0;
}

void mod_print_print_name(const char const *name)
{
   printf("My name is [ %s ]\n", name);

}
Prasoon Saurav
Yes, I have just ran that 'gcc -E main.c'. Very good tip. However, what is the benefit of function marcos like this?
robUK
@robUK: I would never use it, I would prefer _Inline Functions_ rather. Follow this link: http://www.parashift.com/c++-faq-lite/inline-functions.html
Prasoon Saurav
@Prasoon: inlined functions and those macros are unrelated. The macros in the question are intended not to generate code but to generate unique names for the functions --to avoid name collisions. They are some kind of rough approximation to C++ namespaces, where the module is prepended to the name of the function.
David Rodríguez - dribeas
@David: My comment was in general.Agreed with your last comment.
Prasoon Saurav
@David. I think you are right about the name collisions. When would this be a problem? I am interested in this. Do you know of any articles where I can read more about this?
robUK
There can only be one function with a given name in the whole program. Consider that you were simulating C++ containers in C. Both vector and list provide a `push_back` method, and that is not a problem in C++ as they are members of different clases. In C you would have to provide two functions: `push_back( vector*, value )` and `push_back( list*, value )`, but in C there are no overloads (more than one function with the same name and different arguments) so you would have to make different names: `vector_push_back`, `list_push_back`...
David Rodríguez - dribeas
The macro you are using pretty much deals with the same naming pattern: prepend the 'module' name to the function symbol, just instead of doing it manually the macro expands to it: `MODULE_SOURCE_API( vector, push_back )` and `MODULE_SOURCE_API( list, push_back )` will expand to `vector_push_back` and `list_push_back`. I can only assume that the `MODULE_API` is a short hand to avoid having to add the name of the current module, so `MODULE_API(x)` would expand to `MODULE_SOURCE_API( vector, x )` within the vector module.. but that is just a guess. I would handcode the names without the macros.
David Rodríguez - dribeas
@David: Of course, typing such a macro name wouldn't actually be any shorter than just typing out the prefix manually, so it wouldn't really be shorthand. Possibly the intent is to guarantee consistency and to avoid typos in hand-typed prefixes, but I'd still prefer hand-typing since it's less confusing.
jamesdlin