views:

424

answers:

6

I'd like to get the C preprocessor to generate macros for me (i.e., I'm using C99 only). I'd write a macro

#define make_macro(in) <...magic here...>

and when I put

make_macro(name1)
make_macro(name2)

later in the code, it would expand to

#define name1(...) name1_fn(name1_info, __VA_ARGS__)
#define name2(...) name2_fn(name2_info, __VA_ARGS__)

and I'd then be able to use name1 and name2 as (macro-implemented) functions. I think I'm stuck using macros at both steps: it makes sense to use a macro to repeatedly re-fill a template, and the variadic argument handling won't work except via a macro.

So what goes into the <...magic here...> placeholder to do this? At this point, I'm starting to believe that it's not possible in C99, but perhaps I'm missing some details of syntax.

+3  A: 

It's not possible in standard C.

antti.huima
A: 

Try #define make_macro(name,...) name##_fn(name##_info, __VA_ARGS__).

Use like this:

make_macro(name1)
make_macro(name2,1)

and this would generate

name1_fn(name1_info)
name2_fn(name2_info,1)
0x6adb015
+2  A: 

It's not possible because the macro is done only once.

This doesn't mean you could not use other macros in your macro but you could not do

#define TEST #define HALLO 33

int x = TEST;

and expect x to be 33 afterwards! What you would get is a syntax error because you tried

int x = #define HALLO 33;

Or maybe the compiler already complains about #define in #define.

rstevens
+2  A: 

Have you considered using M4 macros? I think they are available on most platforms so that should not be a limitation.

M4 GNU page

nik
+1 , M4 is often overlooked and is a very powerful code generating tool. I wish people would stop with the LISP jokes every time they see me use it, though.
Tim Post
+1  A: 

The problem is that you cannot have #define in a macro - you can pass it though.

#define make_macro(f, d) d f(...) f##_fn(f##_info, __VA_ARGS__)

make_macro(name1, #define)
make_macro(name2, #define)

Ugly but works - I've used similar with gcc.

Edit - doesn't work - at least with my default compiler settings; the macros look correct but the macro calls don't get expanded.

Dipstick
+1  A: 

As everybody has said, you can't do exactly what you are asking for.

You might be able to do something like that by forcing the C preprocesor to run twice, e.g., with a rule like this in the makefile:

.c.pp:
   $(CPP) $< -o $@

Then give your file the extension of test.pp. The Makefile will run it once to generate the .c file, and then the normal run on the .c file will run it a second time.

Personally, I would rather write an external script in Perl or something to generate the C code for me; it's a bit cleaner than playing games with the C pre-processor. It depends on how much code we are talking about.

Chris Arguin