Reuse define statement from .h file in C# code

前端 未结 7 1885
广开言路
广开言路 2021-01-18 14:08

I have C++ project (VS2005) which includes header file with version number in #define directive. Now I need to include exactly the same number in twin C# project. What is th

相关标签:
7条回答
  • 2021-01-18 14:16

    Building on gbjbaanb's solution, I created a .tt file that finds all .h files in a specific directory and rolls them into a .cs file with multiple classes.

    Differences

    • I added support for doubles
    • Switched from try-catch to TryParse
    • Reads multiple .h files
    • Uses 'readonly' instead of 'const'
    • Trims #define lines that end in ;
    • Namespace is set based on .tt location in project

    <#@ template language="C#" hostspecific="True" debug="True" #>
    <#@ output extension="cs" #>
    <#@ assembly name="System.Core.dll" #>
    <#@ import namespace="System" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="System.IO" #>
    <#
    string hPath = Host.ResolveAssemblyReference("$(ProjectDir)") + "ProgramData\\DeltaTau\\";  
    string[] hFiles = System.IO.Directory.GetFiles(hPath, "*.h", System.IO.SearchOption.AllDirectories);
    var namespaceName = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint");
    #>
    //------------------------------------------------------------------------------
    //     This code was generated by template for T4
    //     Generated at <#=DateTime.Now#>
    //------------------------------------------------------------------------------
    
    namespace <#=namespaceName#>
    {
    <#foreach (string input_file in hFiles)
    {
    StreamReader defines = new StreamReader(input_file);
    #>
        public class <#=System.IO.Path.GetFileNameWithoutExtension(input_file)#>
        {
    <#    // constants definitions
    
        while (defines.Peek() >= 0)
        {
            string def = defines.ReadLine();
            string[] parts;
            if (def.Length > 3 && def.StartsWith("#define"))
            {
                def = def.TrimEnd(';');
                parts = def.Split(null as char[], StringSplitOptions.RemoveEmptyEntries);
                Int32 intVal;
                double dblVal;
                if (Int32.TryParse(parts[2], out intVal))
                {
                #>
            public static readonly int <#=parts[1]#> = <#=parts[2]#>;           
    <#
                }
                else if (Double.TryParse(parts[2], out dblVal))
                {
                #>
            public static readonly double <#=parts[1]#> = <#=parts[2]#>;            
    <#
                }
                else
                {
                #>
            public static readonly string <#=parts[1]#> = "<#=parts[2]#>";
    <#          
                }
            }
        } #>
        }
    <#}#>     
    }
    
    0 讨论(0)
  • 2021-01-18 14:16

    MSDN tells us:

    The #define directive cannot be used to declare constant values as is typically done in C and C++. Constants in C# are best defined as static members of a class or struct. If you have several such constants, consider creating a separate "Constants" class to hold them.

    You can create library using managed C++ that includes class - wrapper around your constants. Then you can reference this class from C# project. Just don't forget to use readonly < type > instead of const < type > for your constants declaration :)

    0 讨论(0)
  • 2021-01-18 14:25

    You can achieve what you want in just a few steps:

    1. Create a MSBuild Task - http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
    2. Update the project file to include a call to the task created prior to build

    The task receives a parameter with the location of the header .h file you referred. It then extracts the version and put that version in a C# placeholder file you previously have created. Or you can think using AssemblyInfo.cs that normally holds versions if that is ok for you.

    If you need extra information please feel free to comment.

    0 讨论(0)
  • 2021-01-18 14:29

    I wrote a python script that converts #define FOO "bar" into something usable in C# and I'm using it in a pre-build step in my C# project. It works.

    # translate the #defines in messages.h file into consts in MessagesDotH.cs
    
    import re
    import os
    import stat
    
    def convert_h_to_cs(fin, fout):
        for line in fin:
            m = re.match(r"^#define (.*) \"(.*)\"", line)
            if m != None:
                if m.group() != None:
                    fout.write( "public const string " \
                    + m.group(1) \
                    + " = \"" \
                    + m.group(2) \
                    + "\";\n" )
            if re.match(r"^//", line) != None:
                fout.write(line)
    
    fin = open ('..\common_cpp\messages.h')
    fout = open ('..\user_setup\MessagesDotH.cs.tmp','w')
    
    fout.write( 'using System;\n' )
    fout.write( 'namespace xrisk { class MessagesDotH {\n' )
    
    convert_h_to_cs(fin, fout)
    
    fout.write( '}}' )
    
    fout.close()
    
    s1 = open('..\user_setup\MessagesDotH.cs.tmp').read()
    
    s2 = open('..\user_setup\MessagesDotH.cs').read()
    
    if s1 != s2:
        os.chmod('..\user_setup\MessagesDotH.cs', stat.S_IWRITE)
        print 'deleting old MessagesDotH.cs'
        os.remove('..\user_setup\MessagesDotH.cs')
        print 'remaming tmp to MessagesDotH.cs'
        os.rename('..\user_setup\MessagesDotH.cs.tmp','..\user_setup\MessagesDotH.cs')
    else:
        print 'no differences.  using same MessagesDotH.cs'
    
    0 讨论(0)
  • 2021-01-18 14:33

    I would consider using a .tt file to process the .h and turn it into a .cs file. Its very easy and the source files will then be part of your C# solution (meaning they will be refreshed as the .h file changes), can be clicked on to open in the editor, etc.

    If you've only got 1 #define it might be a little overkill, but if you have a file full of them (eg a mfc resource.h file perhaps) then this solution becomes a big win.

    eg: create a file, DefineConverter.tt and add it to your project, change the marked line to refer to your .h file, and you'll get a new class in your project full of static const entries. (note the input file is relative to your project file, set hostspecific=false if you want absolute paths).

    <#@ template language="C#v3.5" hostspecific="True" debug="True" #>
    <#@ output extension="cs" #>
    <#@ assembly name="System.Core.dll" #>
    <#@ import namespace="System" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="System.IO" #>
    
    <#
    string input_file = this.Host.ResolvePath("resource.h");             <---- change this
    StreamReader defines = new StreamReader(input_file);
    #>
    //------------------------------------------------------------------------------
    //     This code was generated by template for T4
    //     Generated at <#=DateTime.Now#>
    //------------------------------------------------------------------------------
    
    namespace Constants
    {
        public class <#=System.IO.Path.GetFileNameWithoutExtension(input_file)#>
        {
    <#
        // constants definitions
    
        while (defines.Peek() >= 0)
        {
            string def = defines.ReadLine();
            string[] parts;
            if (def.Length > 3 && def.StartsWith("#define"))
            {
                parts = def.Split(null as char[], StringSplitOptions.RemoveEmptyEntries);
                try {
                    Int32 numval = Convert.ToInt32(parts[2]);
                    #>
            public static const int <#=parts[1]#> = <#=parts[2]#>;
    <#
                }
                catch (FormatException e) {
                #>
            public static const string <#=parts[1]#> = "<#=parts[2]#>";
    <#
                }
            }
        } #> 
        }
    }
    
    0 讨论(0)
  • 2021-01-18 14:38

    You can write simple C++/C utility that include this .h file and dynamically create file that can be used in C#.
    This utility can be run as a part of C# project as a pre-build stage.
    This way you are always sync with the original file.

    0 讨论(0)
提交回复
热议问题