tags:

views:

458

answers:

6

I know it is not supported, but I am wondering if there are any tricks around it? Any tips?

Thank you

+5  A: 

Based on the responses to How can I add reflection to a C++ application? (Stack Overflow) and the fact that C++ is considered a "superset" of C, I would say you're out of luck.

There's also a nice long answer about why C++ doesn't have reflection (Stack Overflow).

Andrew Keeton
You can't get it in the language. You can get the equivalent effect by stepping outside the language; see other answers.
Ira Baxter
+2  A: 

You would need to implement it from yourself from the ground up. In straight C, there is no runtime information whatsoever kept on structure and composite types. Metadata simply does not exist in the standard.

Crashworks
Or, if you find implementing a full reflection system all by yourself a bit daunting, you can use a tool designed to analyze/transform code that has all the necessary machinery. See others answers to this question.
Ira Baxter
+2  A: 
  1. Implementing reflection for C would be much simpler... because C is simple language.
  2. There is some basic options for analazing program, like detect if function exists by calling dlopen/dlsym -- depends on your needs.
  3. There are tools for creating code that can modify/extend itselfusing tcc.
  4. You may use the above tool in order to create your own code analizers.
Artyom
can you find the parameters of a function, say sin using dlopen/dlsym? and what are some good code analyzers?
adk
"can you find the parameters of a function" No, just that such symbol exists.
Artyom
+3  A: 

any tricks around it? Any tips?

The compiler will probably optionally generate 'debug symbol file', which a debugger can use to help debug the code. The linker may also generate a 'map file'.

A trick/tip might be to generate and then read these files.

ChrisW
+2  A: 

I needed reflection in a bunch of structs in a C++ project.
I created a xml file with the description of all those structs - fortunately the fields types were primitive types.
I used a template (not C++ template) to auto generate a class for each struct along with setter/getter methods.
In each class I used a map to associate string names and class members (pointers to members).

I didn't regret using reflection because it opened new ways to design my core functionality that I couldn't even imagine without reflection.
(BTW, it was an external report generator for a program that uses a raw database)

So, I used code generation, function pointers and maps to simulate reflection.

Nick D
So you used an ad hoc approach to achieve the desire effect. If that works for you, great. A structured approach to doing what you wanted would have allowed you to skip the hand-coded XML description of those structs, and "reflect" the actual data from the struct declarations themselves. See other answers to this question.
Ira Baxter
+1  A: 

Reflection in general is a means for a program to analyze the structure of some code. This analysis is used to change the effective behavior of the code.

Reflection as analysis is generally very weak; usually it can only provide access to function and field names. This weakness comes from the language implementers essentially not wanting to make the full source code available at runtime, along with the appropriate analysis routines to extract what one wants from the source code.

Another approach is tackle program analysis head on, by using a strong program analysis tool, e.g., one that can parse the source text exactly the way the compiler does it. (Often people propose to abuse the compiler itself to do this, but that usually doesn't work; the compiler machinery wants to be a compiler and it is darn hard to bend it to other purposes).

What is needed is a tool that:

  • Parses language source text
  • Builds abstract syntax trees representing every detail of the program. (It is helpful if the ASTs retain comments and other details of the source code layout such as column numbers, literal radix values, etc.)
  • Builds symbol tables showing the scope and meaning of every identifier
  • Can extract control flows from functions
  • Can extact data flow from the code
  • Can construct a call graph for the system
  • Can determine what each pointer points-to
  • Enables the construction of custom analyzers using the above facts
  • Can transform the code according to such custom analyses (usually by revising the ASTs that represent the parsed code)
  • Can regenerate source text (including layout and comments) from the revised ASTs.

Using such machinery, one implements analysis at whatever level of detail is needed, and then transforms the code to achieve the effect that runtime reflection would accomplish. There are several major benefits:

  • The detail level or amount of analysis is a matter of ambition (e.g., it isn't limited by what runtime reflection can only do)
  • There isn't any runtime overhead to achieve the reflected change in behavior
  • The machinery involved can be general and applied across many languages, rather than be limited to what a specific language implementation provides.
  • This is compatible with the C/C++ idea that you don't pay for what you don't use. If you don't need reflection, you don't need this machinery. And your language doesn't need to have the intellectual baggage of weak reflection built in.

See our DMS Software Reengineering Toolkit for a system that can do all of the above for C, Java, and COBOL, and most of it for C++.

Ira Baxter
What if you don't have the source code?
Crashworks
If you don't have source code, you'd better hope that reflection that answers the specific question you have is available in your programming system. The OP's problem was about C, which has no reflection built in at all. If you have a system with reflection, like Java, you often find it won't give you enough detail; does Java provide the names and types of function parameters, as the OP requested? The point is that you need a powerful system to analyze code, and most programming systems/languages aren't going to provide. So step outside and get a tool that *can*, with no exceptions.
Ira Baxter
Here's another way to think about. Reflection in langauges that have it is about how much of the source code the compiler is willing to leave in your object code to enable reflection. Unless it keeps *all* the source code around, reflection will be limited in its ability to analyze the available facts about the source code.
Ira Baxter