我们C++项目(VS2005)其中包括头文件版本的数量在#define指令。现在我需要包括完全相同的数量在双C#项目。什么是最好的方式来做到这一点?

我想包括此文件作为一种资源,然后分析它在一个运行时与regex恢复版本的数量,但也许有一个更好的办法了,你觉得怎么样?

我不能移动的版本之外。h文件,还建立系统取决于它和C#项目是一个它应当适应。

有帮助吗?

解决方案

你可以实现你想要什么只是几个步骤:

  1. 创建一个MSBuild任务 http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
  2. 更新项目文件包括对任务之前创建的建立

任务接收参与的位置的标题。h文件中,你提到。它然后提取的版本,并把该版本在C#占位的文件以前已经创建。或者你可以认为使用程序集信息.cs通常拥有的版本,如果是确定用于你。

如果你需要的额外信息,请随意见。

其他提示

我会考虑使用的一个。tt文件来处理。h并把它变成一个.cs文件。它非常容易和源文件,然后将部分C#解决方案(这意味着他们将会刷新。h文件的修改),可以点击打开编辑等等。

如果你只有1#定义可能会有点过分,但是如果你有一个文件完整的人(例如一个mfc资源。h文件也许),那么这一解决方案,成为一个大胜利。

例如:创建一个文件,DefineConverter.tt并将它添加到项目中,变化的标记线参考你的.h文件,你会得到一个新的类项目中的全的静态const项。(注意的输入文件是相对于项目文件,设置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]#>";
<#
            }
        }
    } #> 
    }
}

MSDN告诉我们:

#Define指令不能用 宣布恒定值为是 通常在C和C++。常量 C#是最好的定义为静 成员的一类或结构中。如果你 有几个这样的常量,请考虑 创建一个独立的"Constants"类 要保持他们。

你可以创建图书馆采用管理C++,包括类包装你的常数。然后你可以参考这类从C#项目。只是不要忘记使用 只读的 < 类型> 而不是的 const < 类型> 你constants宣言:)

你总是可以使用的预先建立的运行事件C的预处理器上。cs文件和后建立的事件,以撤消的预先建立的步骤。预处理器只是一个文本的替代系统,因此,这是可能的:

// 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";

你可以写简单的C++/C实用工具,包括这一点。h文件和动态创建文件,该文件可以使用。
这个工具可以运行为的一部分C#项目作为一个预建立阶段。
这样你总是同步的,与原始文件。

我写了一python脚本,将#define FOO"条"到的东西用在C#和我使用的是它在预先建立的步骤,在我的C#项目。它的工作。

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

建设gbjbaanb的解决方案,我创建了一个.tt文件,发现所有。h文件中的具体目录和卷入。cs文件与多种类。

差异

  • 我增加支持双打
  • 从试试-抓到TryParse
  • 读取多方面的。h文件
  • 使用'只读'代替'const'
  • 装饰#define线,结束在 ;
  • 名字空间的设定基础。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]#>";
<#          
            }
        }
    } #>
    }
<#}#>     
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top