6

#define ディレクティブにバージョン番号を含むヘッダー ファイルを含む C++ プロジェクト (VS2005) があります。ここで、ツイン C# プロジェクトにまったく同じ番号を含める必要があります。それを行う最良の方法は何ですか?

このファイルをリソースとして含め、実行時に正規表現で解析してバージョン番号を回復することを考えていますが、もっと良い方法があると思いますか?

バージョンを .h ファイルの外に移動することはできません。また、ビルド システムはそれに依存しており、C# プロジェクトは適合させる必要があります。

4

7 に答える 7

6

.tt ファイルを使用して .h を処理し、それを .cs ファイルに変換することを検討します。これは非常に簡単で、ソース ファイルは C# ソリューションの一部になり (つまり、.h ファイルが変更されると更新されます)、クリックしてエディターで開くことができます。

#define が 1 つしかない場合は少しやり過ぎかもしれませんが、それらでいっぱいのファイル (たとえば、mfc resource.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]#>";
<#
            }
        }
    } #> 
    }
}
于 2011-04-12T16:55:55.617 に答える
3

MSDN は次のように説明しています。

#define ディレクティブは、通常 C および C++ で行われているように、定数値を宣言するために使用することはできません。C# の定数は、クラスまたは構造体の静的メンバーとして定義するのが最適です。このような定数が複数ある場合は、それらを保持する別の「定数」クラスを作成することを検討してください。

クラスを含むマネージ C++ を使用してライブラリを作成できます-定数のラッパー。その後、C# プロジェクトからこのクラスを参照できます。定数宣言にconst < type >の代わりにreadonly < type >を使用することを忘れないでください:)

于 2008-09-19T10:14:29.630 に答える
2

あなたはほんの数ステップであなたが望むものを達成することができます:

  1. MSBuildタスクを作成します-http ://msdn.microsoft.com/en-us/library/t9883dzc.aspx
  2. プロジェクトファイルを更新して、ビルド前に作成されたタスクへの呼び出しを含めます

タスクは、参照したヘッダー.hファイルの場所を含むパラメーターを受け取ります。次に、バージョンを抽出し、そのバージョンを以前に作成したC#プレースホルダーファイルに配置します。または、問題がなければ、通常はバージョンを保持するAssemblyInfo.csを使用することもできます。

追加情報が必要な場合は、お気軽にコメントしてください。

于 2008-09-19T10:18:02.333 に答える
2

いつでもビルド前イベントを使用して .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";
于 2008-09-19T10:15:47.393 に答える
1

この.hファイルを含む単純なC++/ Cユーティリティを記述し、C#で使用できるファイルを動的に作成できます。
このユーティリティは、ビルド前の段階としてC#プロジェクトの一部として実行できます。
このようにして、常に元のファイルと同期します。

于 2008-09-19T10:18:21.257 に答える
0

#define FOO "bar" を C# で使用可能なものに変換する Python スクリプトを作成し、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'
于 2008-10-31T19:26:31.867 に答える