【问题标题】:Is it possible to share an enum declaration between C# and unmanaged C++?是否可以在 C# 和非托管 C++ 之间共享枚举声明?
【发布时间】:2009-06-05 04:55:28
【问题描述】:

有没有办法在本地(非托管)C++ 和(托管)C# 之间共享枚举定义?

我在完全非托管代码中使用了以下枚举:

enum MyEnum { myVal1, myVal2 };

我们的应用程序有时会使用托管组件。该 C# 组件通过托管 C++ 互操作 dll(来自本机 dll)将枚举项值作为整数获取。 (互操作 dll 仅在需要 C# 组件时才加载。)C# 组件复制了枚举定义:

public enum MyEnum { myVal1, myVal2 };

有没有办法在不将原生 C++ dll 转换为托管 dll 的情况下消除重复?

【问题讨论】:

    标签: c# c++ enums native managed


    【解决方案1】:

    您可以使用单个 .cs 文件并在两个项目之间共享它。 #include 在 C++ 中的 .cs 文件应该没问题。

    这将是一个示例 .cs 文件:

    #if !__LINE__    
    namespace MyNamespace
    {
        public 
    #endif
    
    // shared enum for both C, C++ and C#
    enum MyEnum { myVal1, myVal2 };
    
    #if !__LINE__
    }
    #endif
    

    如果你想在一个文件中有多个枚举,你可以这样做(尽管你必须暂时将 public 定义为对 C/C++ 来说什么都不是):

    #if __LINE__
    #define public
    #else
    namespace MyNamespace
    {
    #endif
    
        public enum MyEnum { MyEnumValue1, MyEnumValue2 };
        public enum MyEnum2 { MyEnum2Value1, MyEnum2Value2 };
        public enum MyEnum3 { MyEnum3Value1, MyEnum3Value2 };
    
    #if __LINE__
    #undef public
    #else
    }
    #endif
    

    【讨论】:

    • 我刚刚测试了类似的东西 - 但文件名为 MyEnum.cs。所以它编译的是C#,没有任何特殊规则。在我的 C++ 文件中,这是有效的:#include "MyEnum.cs"
    • 感谢您的帮助。确认它按预期工作 - 没有更改 C# 项目设置(除了添加到新 cs 文件的链接)。在 C++ 中看到 .cs 文件的 #include 很有趣。
    • 只需使用:#if __cpulsplus_cli
    • @YochaiTimmer 1. 有一个错字,应该是:__cplusplus_cli; 2.在我看来,__cpulsplus_cli不能帮助区分非托管C++(没有/clr的纯c++)和C#,所以不适合这个问题。
    • 查看编辑历史。似乎这个答案已经被随机的人编辑了很多次。我使用的原始检查是#if WIN32 ...在cli编译器中使用而不是c#
    【解决方案2】:

    感谢分享!

    我玩了一会儿,找到了一种方法来拥有多个枚举和常量声明,而无需大量额外的行:)

    // This is a valid C, C++ and C# file :)
    #if __LINE__
    #define public
    #else
    namespace MyCSharpNamespace{
    #endif
    
        public enum MyConstant { MaxStr = 256 };
        public enum MyEnum1{ MyEnum1_A, MyEnum1_B };
        public enum MyEnum2{ MyEnum2_A, MyEnum2_B };
    
    #if __LINE__
    #undef public
    #else
    }
    #endif
    

    记得将你的文件命名为 *.cs

    【讨论】:

      【解决方案3】:

      您可以将 C# 库暴露给 COM,然后将类型库导入到非托管代码中 - 这样您就可以在非托管库中使用 C# 库中定义的枚举。

      【讨论】:

      • 这是一个有趣的方法。它的副作用是原本未公开的枚举成为 COM 公开的。不幸的是,由于目标操作系统上的框架不兼容,C# 库可能永远无法运行/加载。
      • @sean,您可以有选择地公开特定枚举和不使用 ComVisibleAttribute 的其他枚举。
      【解决方案4】:

      非托管 C++ 和 C# 生活在两个不同的世界中,因此没有办法使用相同的枚举,而无需将 c++ DLL 更改为托管的。

      即便如此,您也可能需要托管 C++ DLL 中的副本。

      C++ 枚举很像一个常量列表,而 C# 枚举继承了 Enum 类,因此提供了很多“技巧”。如您所见,它们非常不同。

      如果本地 C++ DLL 是本地的还是托管的无关紧要,我会将其转换为托管的,并将本地调用包装在托管 C++ 层中。

      这样您就可以在 C++ DLL 中进行枚举复制,并且您可以同时摆脱所有互操作 :-)

      【讨论】:

        【解决方案5】:

        我过去也遇到过同样的问题,并使用预处理器定义解决了它。

        在您的非托管代码中,在您的托管包装器也可以包含的标头内,将您的枚举项放入#define。

        然后,在您的托管和非托管枚举定义中,对两种用法使用相同的#define。

        枚举在托管和非托管世界之间的移动看起来有点讨厌(基本上需要演员表),但对于非托管世界中的调用者来说,它看起来和感觉都很好。

        祝你好运,

        【讨论】:

        • 我遗漏了一些东西...在 C# 中使用标头?
        猜你喜欢
        • 2023-02-20
        • 2015-06-09
        • 1970-01-01
        • 2012-01-10
        • 1970-01-01
        • 1970-01-01
        • 2010-12-29
        • 1970-01-01
        • 2013-11-18
        相关资源
        最近更新 更多