共享来自 C#、C++/CLI 和 C++ 的枚举

发布于 2024-09-09 15:51:27 字数 630 浏览 6 评论 0原文

我有一个由三部分组成的图书馆。首先是本机 C++,它提供实际的功能。其次是 C++ 库的 C++/CLI 包装器/适配器,以简化 C# 到 C++ 的转换。最后,我有一个 C# 库,它通过 C++/CLI 适配器调用 C++ 库。

现在我有两组并行枚举定义,一组存储在 .cs 文件中,另一组存储在 .h 文件中。这带来了双重问题:

  1. 我有双重维护。我必须始终同步两个文件位置中枚举的更改。
  2. 两个枚举使用的命名空间应该相同,但查看两组枚举并在它们之间进行转换的 C++/CLI 包装器会引发命名冲突。

现在我不确定诸如 可以解决这两个问题。想法?

I have a library that consists of three parts. First is native C++, which provides the actual functionality. Second is a C++/CLI wrapper/adaptor for the C++ library, to simplify the C# to C++ transition. Finally I have a C# library, which invokes the C++ library through the C++/CLI adaptor.

Right now there I have two sets of parallel enum definitions, one stored in a .cs file and the other in a .h file. This poses a double problem:

  1. I have dual maintenance. I must always synchronize changes of an enum in both file locations.
  2. The namespace used by both enums should be identical but the C++/CLI wrapper, which views both sets of enums and translates between them, incurs a naming collision.

Right now I'm not sure a solution such as this or that would solve both problems. Thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

戒ㄋ 2024-09-16 15:51:27

即使您在本机 C++ 中包含 C# 枚举(如 第一个链接),两个枚举并不“相同”,C++ 枚举只不过是命名整数的列表,而 C# 枚举是从 Enum 派生的。因此,当尝试同时使用 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::MyEnumEnumShareManaged::MyEnum

编辑:刚刚发现 这篇 SO 帖子 显示了正确的内容在非托管和托管枚举之间进行转换的方式,这肯定也适用于此。例如,在 C++/CLI 中,从托管枚举到非托管枚举的转换可以如下完成:

void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx)
{
    EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx);
    // call a native function "func"
    func(nx);
}

Even if you include the C# enum in your native C++ (as suggested in your first link), both enums are not "the same", the C++ enum is nothing but a list of named integers, while the C# enum is derived from Enum. As a consequence, you get a collision in C++/CLI when trying to use them both.

A possible solution is to use the preprocessor so that your C++/CLI assembly sees both enums in different namespaces:

// 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,
    };
}

In your C++/CLI code, make an inclusion like that:

#undef MANAGED
#include "shared_enum.h"
#define MANAGED
#include "shared_enum.h"

This gives you the availability to distinguish between those two kind of enums
EnumShare::MyEnum or EnumShareManaged::MyEnum in your C++/CLI code.

EDIT: just found this SO post showing the correct way to cast between unmanaged and managed enums, this surely will work here, too. For example, in the C++/CLI, the transition from managed to unmanaged enum can be done like this:

void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx)
{
    EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx);
    // call a native function "func"
    func(nx);
}
层林尽染 2024-09-16 15:51:27

考虑编写代码生成器程序,该程序读取带有枚举的本机 h 文件并生成另一个 h 文件,将枚举转换为 C++/CLI 枚举类。此类代码生成器可在自定义构建步骤的 C++/CLI 项目中使用,生成所需的 CLI 枚举。

我使用这种方法生成本机包装类,以获取非托管 C++ 中的 Enum::GetNames 和 Enum::GetName 函数。

Consider writing code generator program, which reads native h-file file with enumerations and generates another h-file, converting enum to C++/CLI enum class. Such code generator can be used in C++/CLI project on the Custom Build Step, producing required CLI enumerations.

I use this approach to generate native wrapper classes to get Enum::GetNames and Enum::GetName functions in unmanaged C++.

晌融 2024-09-16 15:51:27

只需将 #include "Enum.cs" 指令放入外部命名空间即可解决命名冲突。

编辑:Brent 建议的一种变体是使用 #define 替换 .cs 文件中声明的命名空间之一(甚至枚举名称本身)。这也避免了命名冲突,而不会使命名空间层次结构更深。

Just put your #include "Enum.cs" directive inside an outer namespace to resolve the naming collision.

EDIT: A variation suggested by Brent is to use #define to substitute one of the namespaces (or even the enum name itself) declared in the .cs file. This also avoids the naming collision, without making the namespace hierarchy deeper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文