How can I handle C ++ definitions in C #?

I have a bunch of * .h files containing only c style definitions like

#define ALPHA_REACTOR_CODE 99641 #define BETA_REACTOR_CODE 99642 #define GAMMA_REACTOR_CODE 99643 #define DELTA_REACTOR_CODE 99644 

How can I use these files in my C # code without changes and work with this constant in my code?

+4
source share
4 answers

Apologies for the late reply when I promised earlier.

The idea I have involves using a runtime code compiler, as well as reflection to dynamically create a class containing all of these constants.

So, the steps (or pseudo codes), as I see it, are as follows:

  • For each .h file, read all lines starting with #define and save them.
  • Using Microsoft.CSharp.CSharpCodeProvider() and an empty template file, compile the DLL in memory, which contains a class that provides style constants public const int ALPHA_REACTOR_CODE = 99641; .
  • Use Assembly.GetType(string) to get the type of the generated class
  • Use Reflection and a method that takes a constant name to access a value.

So, if this is our attack plan, here are some pieces of code that can help you.

1. Downloading .h files This is a fairly simple file reading, the key trick is to filter your lines by #define and then parse them into Dictionary<string, int> .

 lines.Where(line => line.StartsWith("#define", true, CultureInfo.CurrentCulture)) .Select(line => line.Split(' ').Skip(1)) .ToDictionary(lineParts => lineParts.First(), lineParts => int.Parse(lineParts.Last())); 

This will create a dictionary of all your definitions. You can call .Distict() to .ToDictionary() only if duplicate definitions exist.

2. Create an assembly Here you use Microsoft.CSharp.CSharpCodeProvider() to create an assembly in memory. The trick here is to have a GenerateCode.cs file that contains the base structure for the class. This must be set as EmbeddedResource, otherwise it will try and be compiled (which will not work).

 using System; namespace GeneratedCode {{ public class GeneratedConstants {{ {0} }} }} 

You will notice {0} , we use this with string.Format to insert constants into the file.

Use assembly.GetManifestResourceStream() to get the stream of this template file and a regular StreamReader to read it into one large line in memory.

Generate constants using StringBuilder and basic string.Format() formatting in combination with the Value Dictionary.

  StringBuilder builder = new StringBuilder(); foreach (var constant in dict) { builder.AppendFormat(CultureInfo.CurrentCulture, "public const int {0} = {1};", constant.Key, constant.Value); } 

Then just use string.Format () to insert the builder string into the string of the generated class (using {0} )

Then you just need to use Microsoft.CSharp.CSharpCodeProvider() to assemble the assembly in memory.

  using (CSharpCodeProvider provider = new CSharpCodeProvider()) { parameters.ReferencedAssemblies.Add("System.dll"); parameters.ReferencedAssemblies.Add("System.Core.dll"); CompilerResults results = provider.CompileAssemblyFromSource(parameters, sourceCode); } 

3 and 4. Using Reflection now you have an assembly containing a type with constants defined in it, you can use assembly.GetType("GeneratedCode.GeneratedConstants"); to get the type and use Reflection to get the constants one at a time or all together.

Have a look at this blog post which tells how to get const using reflection: http://weblogs.asp.net/whaggard/archive/2003/02/20/2708.aspx

Ok, hope this helps you. This is not a difficult decision, but has several moving parts.

Good luck

+3
source

Write a program to convert the .h style file to the C equivalent. If, as claimed, the .h file contains only int #defines, this should be pretty trivial in your language of choice.

Ideally, the conversion will be properly integrated into your build / build process, so it will be redone if / if the .h file changes.

+2
source

I do not know if what you want is possible. However, for what stands here, this is the C # way:

C # does not support #define in the same way that C ++ does. I think you will have to write these constants as enums or const values. eg.

 enum REACTOR { ALPHA = 99641, BETA = 99642, GAMMA = 99643, DELTA = 99641 } 

or use constants since these values โ€‹โ€‹are replaced at compile time

 const int ALPHA_REACTOR = 99641; 

If you have a lot of these values โ€‹โ€‹(.h classes), I suppose you could create a โ€œpersistentโ€ container class that contains all of them in separate enums describing the values โ€‹โ€‹inside (REACTOR, X, Y, Z), so you you can just call Constants.REACTOR.ALPHA in your code.

You preferred this post as I am interested in the actual answer to this question. I am wondering if it is possible what you want to do.

// edit This link offers another option, which I cited below.

If you want, there is an alternative path that you might want to explore: Create an assembly that has all the constants, refer to it from your assembly and then compile. Constant values โ€‹โ€‹will be copied to your code, and since the assembly of constants will never be used, it will never look, letting you just not distribute it.

I would recommend this only after very intensive testing, as I am not sure that all JIT implementations will really allow this.

This is not the same, but another option that generates additional C # code.

+1
source

Perhaps you want managed C ++ to integrate your C code with C # code?

0
source

All Articles