How to generate C code automatically [closed]

走远了吗. 提交于 2020-05-12 01:05:59

问题


I am working on a project in C. I observe that a lot of code can be automatically generated based on certain rules. ie. if I specify just C structures, based on that, the code can be automatically generated. I know it can be done, but I havent done it before. It will be nice if experienced C programmers can give certain pointers or share their experience on how to do such things with minimum engineering effort.

EDIT: To be very specific, do I need to write a custom parser in C to do all that or is there some easier way to deal with this?


回答1:


The easy part has to do with 1:1 syntax replacement.

The hard part is doing anything terribly meaningful beyond 1:1 syntax replacement.

If you rely too heavily on macros, you run into the (made up name) issue of cognitive drift, where you are now designing your own language (a macro one) but the compiler and running program is using another. Simple mappings don't make the new language more cumbersome, but even simple mappings get complex far too quickly due to macros functioning on a text only substitution level.

If you are using C++, then a far better solution is to use templates. Templates offer many of the same features as macros, except that they don't suffer from as much cognitive drift, because templates substitute with awareness of the type system.

As the syntax and meaning of C-like language structure evolves, you find that newer languages often try to "fix" issues with the amount of repetitive code required by a pure C solution. Try learning a few new languages that are "near" C and you will get an appreciation for ways this code duplication can be reduced, leading to better choices in "generation" efforts in C.




回答2:


One relatively traditional way to do metaprogramming in C is with a technique like X macros.

In essence, rather than using plain C structure declarations, define the structures entirely using macros, something like this

BEGIN_STRUCT(pointf)
FIELD(float, x)
FIELD(float, y)
END_STRUCT(pointf)

and place these definitions in a header file with no guards against multiple inclusion.

Then, for each piece of code you need to generate (including the basic structures), #define each of the metalanguage macros, #include the definitions header, and #undef the metalanguage macros again:

#define BEGIN_STRUCT(N) struct N {
#define FIELD(T,N) T N;
#define END_STRUCT(N) }
#include "definitions.h"
#undef BEGIN_STRUCT
#undef FIELD
#undef END_STRUCT



回答3:


One effective way I have seen is to use macros (an often hated tool). Macros have two features that can help make life much easier, the single hash '#' which can turn a parameter into a string, i.e. #_name will be translated into "fieldName1" and the double hash '##' which concatenate parameters with other things which in turn can expand new things, i.e. STRUCT_##_type##_str that will be translated into STRUCT_int_str which will be translated into "%d"

First wrap the structure or "description" in macros i.e. into an own file (the-struct.def)

STRUCT_BEGIN(s_my_struct)
  STRUCT_FIELD(int, fieldName1)
  STRUCT_FIELD(int, fieldName2)
  STRUCT_FIELD(int, fieldName3)
STRUCT_END(s_my_struct)

// Note that you can add more structs here and all will automatically get defined and get the print function implemented 

Then one can define the macros differently in places where one want to declare or implement things that should handle the struct. i.e.

#define STRUCT_BEGIN(_name) struct _name {
#define STRUCT_END(_name) };
#define STRUCT_FIELD(_type, _name) _type _name;

#include "the-struct.def"

// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD

and to make a function that prints the struct

#define STRUCT_BEGIN(_name) void print_ ## _name(struct _name *s) {
#define STRUCT_END(_name) }
#define STRUCT_FIELD(_type, _name) printf("%s = " STRUCT_##_type##_str "\n", #_name, s->_name); 
#define STRUCT_int_str "%d" /* this is to output an int */
// add more types...

#include "the-struct.def"

// then undef them
#undef STRUCT_BEGIN
#undef STRUCT_END
#undef STRUCT_FIELD
#undef STRUCT_int_str

other uses can be to auto-generate functions to ie swap bytes etc.

Made a small example as a gist here https://gist.github.com/3786323



来源:https://stackoverflow.com/questions/12591767/how-to-generate-c-code-automatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!