如何在c#中处理c++定义

本文关键字:处理 c++ 定义 | 更新日期: 2023-09-27 18:10:28

我有一堆*.h文件,只包含c风格的定义,如

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

我如何在我的С#代码中使用这个文件而不进行更改,并在我的代码中使用这个常量?

如何在c#中处理c++定义

很抱歉我早前答应给你答复。

我的想法是使用运行时代码编译器和反射来动态生成一个包含所有这些常量的类。

所以我看到的步骤(或伪代码)是:
  1. 对于每个。h文件,读取所有以#define开头的行并存储它们。
  2. 使用Microsoft.CSharp.CSharpCodeProvider()和一个空模板文件,在内存中编译一个DLL,其中包含一个暴露public const int ALPHA_REACTOR_CODE = 99641;风格常量的类。
  3. 使用Assembly.GetType(string)获取生成的类的类型
  4. 使用反射和一个接受常量名的方法来访问值

如果这是我们的攻击计划,这里有一些代码片段可能会帮助你。

1。加载.h文件这是非常基本的文件读取,关键技巧是通过#define过滤行,然后解析为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()));

这将生成一个包含所有定义的字典。您可能希望在.ToDictionary()之前执行.Distict()调用,以防存在重复的定义。

2。生成程序集这是使用Microsoft.CSharp.CSharpCodeProvider()在内存中生成程序集的地方。这里的技巧是有一个"generatcode .cs"文件,其中包含一个类的基本结构。这必须设置为EmbeddedResource,否则它将尝试编译(这将不起作用)。

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

您将注意到{0},我们使用string.Format将常量插入到文件中。

使用assembly.GetManifestResourceStream()获取该模板文件的流,并使用正常的StreamReader将其读入内存中的一个大字符串。

通过使用StringBuilder和基本string.Format()格式以及值字典来生成常量。

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

然后使用string. format()将构建器字符串插入生成的类字符串(使用{0})

然后,您只需要使用Microsoft.CSharp.CSharpCodeProvider()在内存中生成程序集。

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

3,4. 使用反射现在你有了一个包含类型的程序集,其中定义了你的常量,你可以使用assembly.GetType("GeneratedCode.GeneratedConstants");来获得类型,并使用反射来获得常量,一次一个或全部。

看看这篇介绍如何使用反射获取const的博文:http://weblogs.asp.net/whaggard/archive/2003/02/20/2708.aspx

我希望这能帮到你。这不是一个过于复杂的解决方案,但有几个可移动的部分。

祝你好运!

编写程序将C风格的.h文件转换为c#等效文件。如前所述,如果.h文件只包含int #定义,那么在您选择的语言中,这应该是相当微不足道的。

理想情况下,转换将被正确地集成到你的构建/制作过程中,这样当.h文件发生变化时,它将被重新完成。

我不知道你想要的是否可能。然而,值得注意的是c#的方法:

c#不像c++那样支持#define。我认为你必须把这些常量写成枚举或const值。例如

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

或使用常量,因为这些值在编译时被替换

const int ALPHA_REACTOR = 99641;

如果你有很多这样的值(一个。h类),我想你可以做一个"常量"容器类,把它们放在单独的枚举中,描述里面的值(REACTOR, X, Y, Z),这样你就可以简单地在你的代码中调用Constants.REACTOR.ALPHA。

喜欢这个帖子,因为我对这个问题的实际答案很感兴趣。我想知道你想做什么是否可能。

//编辑这个链接暗示了另一种选择,我在下面引用了。

如果你愿意,你可以选择另一条路径:创建包含所有常量的程序集,从程序集,然后进行编译。常量值将被复制到您的代码,并且由于常量的程序集永远不会被使用,因此它将永远不会被查找,允许您简单地不分发它。

我只会推荐一些非常广泛的测试后,因为我我不确定所有的JIT实现都会允许这个

这是另一个选项,可以生成额外的c#代码。

也许您希望托管c++将您的C代码与c#代码集成?