在 C# 和 C++ 之间共享源文件
Sharing Source files between C# and C++
我有一个主要用C#编写的项目。我需要为该项目的 API 的所有错误号"定义"定义一个类。我试图避免编写/更改我的许多代码生成器之一来实现这一目标。
我想做的是能够将内容(如错误删除)直接#include
到 C/C++ 项目中。我在 C# 中按如下方式定义了它们,并且我没有对您将在此处看到的内容使用枚举:
using System;
namespace ProjectAPI {
[Serializable]
public sealed class ProjectError {
public enum ProjectErrorClass {
None = -1,
Undefined = 0,
Login,
Store,
Transaction,
Heartbeat,
Service,
HTTPS,
Uploader,
Downloader,
APICall,
AutoUpdate,
General
}
public enum ProjectErrorLevel {
Unknown = -1,
Success = 0,
Informational,
Warning,
Critical,
};
/// <summary>
/// PROJECT_ERROR_BASE - This is the base for all Project defined errors in the API. Project Errors are defined as follows:
/// ProjectAPI error values are 32 bit values defined as follows:
/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
/// +---+---------------+-----------------------+------------------+
/// |Sev|Error Code Base| Error Class |Unique Error Code |
/// +---+---------------+-----------------------+------------------+
/// where
///
/// Sev - is the severity code of the error (2 bits), and is defined as follows:
/// 00 - Success (non-fatal) 0x00
/// 01 - Informational 0x01
/// 10 - Warning 0x02
/// 11 - Error 0x03
///
/// Error Code Base - is the starting point of all Project Errors, and is set at 0xA4 (8 Bits).
///
/// Error Class - is the error class, or API "Module" that caused the error (12 bits).
///
/// Code - the unique error code (10 bits). (0 - 1,023 (0x3FF)).
/// </summary>
private static readonly int ERR_SHIFT = 0x1E;
private static readonly int BASE_SHIFT = 0x16;
private static readonly int CLASS_SHIFT = 0x06;
private static readonly int PROJECT_SEV_SUCCESS = 0x00;
private static readonly int PROJECT_SEV_INFO = 0x01;
private static readonly int PROJECT_SEV_WARN = 0x02;
private static readonly int PROJECT_SEV_ERROR = 0x03;
private static readonly int PROJECT_ERROR_BASE = 0xA5;
/// <summary>
/// Project Error Class Constants:
/// </summary>
private static readonly int PROJECT_ERROR_CLASS_UNDEF = 0x0010; /// Undefined.
private static readonly int PROJECT_ERROR_CLASS_LOGIN = 0x0020; /// LoginClass Error.
private static readonly int PROJECT_ERROR_CLASS_STORE = 0x0040; /// Store Error.
private static readonly int PROJECT_ERROR_CLASS_TRANS = 0x0080; /// Transaction Error.
private static readonly int PROJECT_ERROR_CLASS_HEART = 0x0100; /// HeartBeat (Project Health Monitor) Error.
private static readonly int PROJECT_ERROR_CLASS_SERV = 0x0200; /// Service Error.
private static readonly int PROJECT_ERROR_CLASS_HTTP = 0x0400; /// HTTP/HTTPS Error.
private static readonly int PROJECT_ERROR_CLASS_UPLOAD = 0x0800; /// Upload (Transactions) Error
private static readonly int PROJECT_ERROR_CLASS_DOWNLOAD = 0x1000; /// Download (Transactions) Error
private static readonly int PROJECT_ERROR_CLASS_APICALL = 0x2000; /// API Command/call error.
private static readonly int PROJECT_ERROR_CLASS_UPDATE = 0x4000; /// Auto-Updater Errors.
private static readonly int PROJECT_ERROR_CLASS_GEN = 0x8000; /// General Error.
public static readonly int PROJECT_ERROR_UNKNOWN_ERROR = ProjectErrCode(PROJECT_SEV_ERROR, PROJECT_ERROR_CLASS_GEN, 0x001);
// Was...
// (((PROJECT_SEV_ERROR << ERR_SHIFT) | PROJECT_ERROR_BASE << BASE_SHIFT) | ((PROJECT_ERROR_CLASS_UNDEF << CLASS_SHIFT) | 0x0001));
public static readonly int PROJECT_ERROR_UNKNOWN_HEARTBEAT_ERROR = ProjectErrCode(PROJECT_SEV_ERROR, PROJECT_ERROR_CLASS_HEART, 0x001);
...Snip...
。
我意识到还有其他东西可以放入 Enums 中,但我的目标是能够使用 C++ 编译器编译此源代码。(上面的示例中缺少一些函数,即从 API 调用时构建错误代码 OTF 的最终整数值的ProjectErrCode()
。
我正在构建注释中看到的错误常量,我可以回到那个,但我宁愿编写类似的类 - 一个在 C# 中,一个在 C++ 中可以构造/解构错误代码。我的函数返回错误的严重性、错误类等。开发人员可以忽略它,记录它,将其传递给UI等。
如果我只有 5 或 10 个错误代码,这将不是问题。但是我有 100 多个,真的不想维护带有重复信息的 .cs 和 .h 文件。我可以在 .h 文件中管理它们并让 CS 代码读取它们,但这几乎与编写(修改)代码生成器一样多。
如何#define
单个源文件,以便 C# 编译器可以编译它,就像 C/++ 编译器也可以编译一样? 我可以简单地#include "ProjectErrors.cs"
- 文件名不是问题。我开始认为我可以通过#define
像using System;
这样的东西来做到这一点,但几乎被挂在那里了。
1) 使用预处理器。一些 ifdef 和定义应该可以解决问题,但它会非常混乱。
2) 使用 C++/CLI。C++/CLI 是编译为 .Net 程序集的 C++ 的变体。虽然 .Net 类型和本机类型是单独的实体,但它们之间的转换是可能的。
例如,您将标头定义为具有本机枚举和常量的完全本机代码;然后,您可以将此标头包含在 100% 本机项目和 C++/CLI 项目中,这还将提供枚举到相应 .Net 类型的转换(请参阅此线程)。
如果你不想有这个中间转换层,C++/CLI 还为您提供了C++宏的全部功能,因此您可以创建一个包含 ENUM_HEADER 和 CONSTANT 等宏的文件,并以相当干净和直接的方式将它们评估为适当的托管或本机形式(你不能用 C# 做到这一点,因为它的预处理器要弱得多)。然后,生成的程序集本质上就是这个标头和适当的宏定义,而不是其他任何内容。
3)在某些外部文件(XML,INI等)中定义值,并且仅在C#和C++中实现加载逻辑(这实际上可能是最干净的解决方案)。
一种选择是使用 T4:这是 Visual Studio 中内置的代码生成语言。它主要用于 C#,但C++也同样有效。
使用预处理器遇到困难的原因之一是 C# 和 C++ 具有相同的注释语法:您将无法使用注释隐藏C++预处理器的不兼容的 C# 特定语法。也就是说,您可以尝试VB :)。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 在cuda线程之间共享大量常量数据
- 如何从具有移动语义的类对象中生成共享指针
- 在c代码之间共享数据的最佳方式
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 将静态库链接到不带-fPIC的共享库中
- 为测试目标创建具有不同源文件夹的文件
- C++两个源文件之间共享的枚举的静态实例
- 构建并使用使用另一个共享库的源文件中的共享库.(Rinside)
- 我应该在源文件之间共享的常量的定义中添加关键字"extern"吗
- 如何在GLFW 3中的源文件之间共享窗口上下文
- 在 C# 和 C++ 之间共享源文件
- 如何使用 extern 在 C++ 中的源文件之间共享地球变量
- 如何更改从多个源文件编译的g++生成的Linux共享库的入口点
- 具有公共源文件的一个项目中的多个共享库
- 在c/c++中,在源文件之间共享变量的最佳策略是什么
- 在项目之间共享源文件
- 如何使用CMake为静态库创建共享库包装器(不使用源文件)
- 如何在c++11和c++98的共享库创建中使用cmake 2.8.2进行单次构建时每次重新编译源文件