Совместное использование исходных файлов между C # и переполнением стека

У меня есть проект, который в основном написан на C #. Мне нужно определить класс для всех ошибок номер «определяет» для API этого проекта. Я пытаюсь избежать написания / изменения одного из моих многочисленных генераторов кода для достижения этой цели.

То, что я хотел бы сделать, это уметь #include содержимое (например, ошибка очищается) непосредственно в проект C / C ++. Я определил их в C # следующим образом, и я не использовал enum для вещей, которые вы увидите здесь:

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 ++. (В приведенном выше примере отсутствуют функции, а именно: ProjectErrCode() который строит окончательное целочисленное значение кода ошибки OTF при вызове из API.)

Я строил константы ошибок, как видно из комментариев, и я могу вернуться к этому, но я бы предпочел написать похожие классы — один на C #, другой на C ++, который может создавать / восстанавливать коды ошибок. Мои функции возвращают серьезность ошибки, класс ошибки и т. Д. Разработчик может игнорировать это, регистрировать его, передавать в пользовательский интерфейс и т. Д.

Если бы у меня было только 5 или 10 кодов ошибок, это не было бы проблемой. Но у меня есть более 100, и я действительно не хочу иметь файл .cs и .h с дублирующейся информацией. Я могу управлять ими в файле .h и иметь код CS для их чтения, но это почти такая же работа, как написание (изменение) генератора кода.


Как я могу #define мой путь к одному исходному файлу, так что компилятор C # может скомпилировать его, точно так же, как компилятор C / ++ тоже может? Я мог бы просто #include "ProjectErrors.cs" — Имя файла не является проблемой там. Я начал думать, что смогу сделать это #defineтакие вещи, как using System; но в значительной степени повесили там.

7

Решение

1) Используйте препроцессор. Некоторые ifdefs и define должны справиться с задачей, но это было бы очень грязно.

2) Используйте C ++ / CLI. C ++ / CLI — это вариант C ++, который компилируется в сборки .Net. Хотя типы .Net и собственные типы являются отдельными объектами, возможны преобразования между ними.

Например, вы определяете заголовок как полностью нативный код с нативными перечислениями и константами; затем вы можете включить этот заголовок как в 100% собственный проект, так и в проект C ++ / CLI, который также обеспечит преобразования (увидеть эту тему) перечислений к соответствующим типам .Net.

Если вы не хотите иметь этот промежуточный уровень преобразования, C ++ / CLI также предоставляет вам все возможности макросов C ++, поэтому вы можете создать файл с макросами, такими как ENUM_HEADER и CONSTANT, и оценить их в соответствующие управляемые или собственные формы в довольно чистый и простой способ (что вы не можете сделать с C #, потому что он имеет гораздо более слабый препроцессор). Результирующая сборка будет тогда, по сути, этим заголовком и соответствующими определениями макросов и ничего больше

3) Имейте значения, определенные в каком-то внешнем файле (XML, INI, что угодно …) и реализуйте логику загрузки только в C # и C ++ (это может быть самым чистым решением).

4

Другие решения

Одним из вариантов является использование T4Это язык генерации кода, встроенный в Visual Studio. Это в основном используется в C #, но C ++ явно работает тоже.

Одна из причин, по которой вам будет трудно работать с препроцессором, состоит в том, что C # и C ++ имеют одинаковый синтаксис для комментариев: вы не сможете скрыть несовместимый специфичный для C # синтаксис для препроцессора C ++, используя комментарий. Тем не менее, вы можете попробовать VB :).

4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector