代码之家  ›  专栏  ›  技术社区  ›  tomash

在C#代码中重用.h文件中的define语句

  •  6
  • tomash  · 技术社区  · 18 年前

    我有C++项目(VS2005),其中包含了在版本定义指令中的版本号的头文件。现在我需要在twin C#项目中包含完全相同的数字。最好的方法是什么?

    我无法将版本移到.h文件之外,构建系统也依赖于它,而C#项目是一个应该调整的项目。

    7 回复  |  直到 10 年前
        1
  •  6
  •   gbjbaanb    15 年前

    我会考虑使用.TT文件来处理.h,并将其转换成.cs文件。这非常简单,源文件将成为C#解决方案的一部分(意味着它们将随着.h文件的更改而刷新),可以单击以在编辑器中打开,等等。

    例如:创建一个文件,定义converter.tt并将其添加到您的项目中,更改标记行以引用您的.h文件,您将在项目中得到一个新的类,其中充满静态常量条目。(注意,输入文件是相对于项目文件的,如果需要绝对路径,请设置hostspecific=false)。

    <#@ 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]#>";
    <#
                }
            }
        } #> 
        }
    }
    
        2
  •  3
  •   aku    18 年前

    MSDN告诉我们:

    无法使用#define指令 通常在C和C++中完成。常数 在C#中,最佳定义为静态 类或结构的成员。如果你 有几个这样的常数,考虑一下

    可以使用托管C++创建库,其中包含了围绕常量的类包装器。然后您可以从C#project中引用这个类。只是别忘了使用 只读<类型> 而不是 对于常量声明:)

        3
  •  2
  •   Jorge Ferreira    18 年前

    只需几个步骤,您就可以实现您的目标:

    1. http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
    2. 更新项目文件以包含对生成之前创建的任务的调用

    任务将收到一个参数,其中包含您引用的header.h文件的位置。然后,它提取版本并将该版本放入先前创建的C#占位符文件中。或者您也可以考虑使用AssemblyInfo.cs,如果这对您合适的话,它通常会保存版本。

    如果您需要更多信息,请随时发表评论。

        4
  •  2
  •   Tim Cooper    14 年前

    您可以始终使用预构建事件在.cs文件上运行C预处理器,使用后构建事件撤消预构建步骤。预处理器只是一个文本替换系统,因此这是可能的:

    // version header file
    #define Version "1.01"
    
    // C# code
    #include "version.h"
    // somewhere in a class
    string version = Version;
    

    预处理器将生成:

    // C# code
    // somewhere in a class
    string version = "1.01";
    
        5
  •  1
  •   Ilya    18 年前


    此实用程序可以作为C#project的一部分作为预构建阶段运行。

        6
  •  1
  •   JKoplo    10 年前

    在gbjbaanb的解决方案的基础上,我创建了一个.tt文件,该文件可以查找特定目录中的所有.h文件,并将它们滚动到一个包含多个类的.cs文件中。

    分歧

    • 我增加了对双打的支持
    • 读取多个.h文件
    • 使用“只读”而不是“常量”
    • 修剪#定义以 ;
    • 命名空间是基于项目中的.tt位置设置的

    <#@ 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]#>";
    <#          
                }
            }
        } #>
        }
    <#}#>     
    }
    
        7
  •  0
  •   Corey Trager    17 年前

    # 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'