从C#,C+共享枚举+/CLI和C++;

从C#,C+共享枚举+/CLI和C++;,c#,.net,c++,enums,c++-cli,C#,.net,C++,Enums,C++ Cli,我有一个由三部分组成的图书馆。首先是本地C++,它提供实际功能。第二个是C++库的C++/CLI包装/适配器,简化C++到C++的转换。最后,我有一个C语言库,它通过C++/CLI适配器调用C++库。 现在我有两组并行枚举定义,一个存储在.cs文件中,另一个存储在.h文件中。这带来了双重问题: 我有双重保养。我必须始终同步两个文件位置中枚举的更改 两个枚举使用的名称空间应该相同,但是查看两组枚举并在它们之间进行转换的C++/CLI包装器会导致命名冲突 现在我不确定这样的解决方案是否能同时解决这两

我有一个由三部分组成的图书馆。首先是本地C++,它提供实际功能。第二个是C++库的C++/CLI包装/适配器,简化C++到C++的转换。最后,我有一个C语言库,它通过C++/CLI适配器调用C++库。 现在我有两组并行枚举定义,一个存储在.cs文件中,另一个存储在.h文件中。这带来了双重问题:

  • 我有双重保养。我必须始终同步两个文件位置中枚举的更改
  • 两个枚举使用的名称空间应该相同,但是查看两组枚举并在它们之间进行转换的C++/CLI包装器会导致命名冲突
  • 现在我不确定这样的解决方案是否能同时解决这两个问题。思想?

    < P>即使你在你的C++中包含了C++的枚举(如你所建议的),两个枚举都不是“相同的”,C++枚举只是一个命名整数的列表,而C是从枚举中派生出来的。因此,在尝试同时使用C++/CLI时,会在C++/CLI中发生冲突

    一种可能的解决方案是使用预处理器,以便您的C++/CLI程序集可以在不同的命名空间中看到这两个枚举:

    // shared_enum.h
    
    #undef ENUMKEYWORD
    #undef ENUMNAMESPACE
    
    #ifdef MANAGED
    #define ENUMKEYWORD public enum class
    #define ENUMNAMESPACE EnumShareManaged
    #else
    #define ENUMKEYWORD enum
    #define ENUMNAMESPACE EnumShare
    #endif
    
    namespace ENUMNAMESPACE
    {
        ENUMKEYWORD MyEnum
        {
            a = 1,
            b = 2,
            c = 3,
        };
    }
    
    在您的C++/CLI代码中,包含如下内容:

    #undef MANAGED
    #include "shared_enum.h"
    #define MANAGED
    #include "shared_enum.h"
    
    这使您能够区分这两种枚举 C++/CLI代码中的
    EnumShare::MyEnum
    EnumShareManaged::MyEnum

    编辑:刚刚发现显示了在非托管和托管枚举之间强制转换的正确方法,这在这里肯定也适用。例如,在C++/CLI中,从托管枚举到非托管枚举的转换可以如下所示:

    void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx)
    {
        EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx);
        // call a native function "func"
        func(nx);
    }
    
    void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx)
    {
    EnumShare::MyEnum nx=静态_转换(mx);
    //调用本机函数“func”
    func(nx);
    }
    
    考虑编写代码生成器程序,该程序读取带有枚举的本机h文件,并生成另一个h文件,将枚举转换为C++/CLI枚举类。这种代码生成器可以在定制构建步骤的C++/CLI项目中使用,生成所需的CLI枚举

    < P>我使用这个方法生成本地包装类,以获得EnUM::GETNAME:EnUM::GETNEX函数在非托管C++中。

    < P>只需将您的<代码>包含“EnUn.cs”< /C> >指令,在外部命名空间内解决命名冲突。< /P> 编辑:Brent建议的一种变体是使用
    #define
    替换.cs文件中声明的一个名称空间(甚至是枚举名称本身)。这还避免了命名冲突,而不会使命名空间层次结构更深。

    不是重复,但请参见类似问题:@Billy:的可能重复:它不是重复,因为这里的C++/CLI层提供了一些附加选项。尽管如此,你在帖子中给出的答案在这里也可能有帮助。把这两个解决方案放在一起,你就完了?!附加要求:我的C#客户端是“AnyCPU”,支持的C++/CLI必须同时支持x86/x64部署。这意味着C#客户端在运行时加载C++/CLI明确性;从C#到C++/CLI的构建时依赖关系不是一个选项。C#程序集如何查看“shared#u enum.h”文件?我猜想C++比“C”包含一个“SyddEnEn.cs”要容易,而不是C语言不知怎么吸收了“SyddEnEn.h”。是吗?@Mystagogue:如果您在某个CPP文件(C++/CLI项目)中包含“托管”共享_enum.h,托管enum将成为程序集的一部分,并且如果您从C#引用此程序集,它将在其中可见,因为它已声明为“public”。另一方面,如果在“shared_enum.cs”中声明托管枚举,它将在C++/CLI项目中不可见,因为C++/CLI不引用您的C#项目,反之亦然。啊!是的,但是该死!附加要求:我需要同时支持x86和x64部署。我的“AnyCPU”C#客户机代码当前引用了一个中间人C#程序集,其中包含接口和枚举定义。同样引用中间人的C++/CLI x86/x64在运行时由C#client根据体系结构显式加载。简言之,我不能使用依赖于C++/CLI程序集上的C#“构建时”引用的技术。@Mystagogue:是的,当我阅读您给出的第一个引用的解决方案(包括“shared#u enum.cs”)时,首先想到的是在枚举中使用额外的C#程序集。但我认为这将是一些可以避免的开销,因此我制定了一个更适合您首先描述的情况的解决方案。尽管如此,即使使用中间人C#程序集,基本问题仍然是相同的——两种类型的枚举必须位于不同的名称空间中。IMHO最干净的方法是使用一个简单的代码生成器(就像Alex Farber建议的那样),因为C#缺少预处理器。在一个大型项目中处理大约50个枚举时也使用了这种方法。最重要的部分是将托管枚举数设置为未更改的枚举数值。即使使用代码生成器(如果有多个枚举,这可能会很有用),您也必须以某种方式处理命名冲突问题。我的建议是“使用不同的名称空间并正确处理它们”。还有更好的方法吗?你的方法不允许在C语言和本地C++项目中直接使用同一个源文件。Mine不需要宏。您的方法不允许从C++/CLI项目访问托管枚举,只允许访问非托管枚举。因此它不符合OP的要求。实际上,如果:(1)我使用的是只包含枚举的C#middle man项目,(2)C++/CLI项目引用“middle man”C#项目,以及(3)我使用带有名称空间的#include“enum.cs”,那么这种方法确实允许访问托管枚举。这种方法还可以处理我的x86/x64部署需求。但这种方法确实存在两个(小的?)问题。冷杉