Architecture

Runtime layers, namespace design, and key architectural decisions.

Layer Overview

sharp-runtime is organized into three conceptual layers:

┌──────────────────────────────────────────────┐
│              CNA / mobile-eggbert            │  ← Consumer projects
├──────────────────────────────────────────────┤
│            System::* namespaces              │  ← sharp-runtime public API
│  (String, Array, Exception, IO, Threading…)  │
├──────────────────────────────────────────────┤
│          SharpRuntime:: helpers              │  ← Primitive types, macros
│  (intcs, bytecs, SharpRuntimeHelper.hpp)     │
├──────────────────────────────────────────────┤
│        C++ Standard Library + STL           │  ← std::string, std::vector…
│     + Vendored: ZLIB, tinyxml2, miniz        │
└──────────────────────────────────────────────┘

Namespace Structure

All public API lives in the System namespace or its sub-namespaces, mirroring .NET conventions:

NamespaceDescription
SharpRuntimePrimitive type aliases (intcs, bytecs, etc.) and utility macros
SharpRuntime::StorageStorage path utilities for isolated storage
SystemCore types: Object, String, Array, Exception, Math, DateTime, etc.
System::CollectionsNon-generic collections: ArrayList, Hashtable, BitArray
System::Collections::GenericGeneric: List<T>, Dictionary<K,V>, HashSet<T>, Queue<T>, etc.
System::Collections::ConcurrentThread-safe collections
System::Collections::ImmutableImmutable collection types
System::Collections::ObjectModelCollection base classes: Collection<T>, ObservableCollection<T>
System::IOStream, File, Directory, Path, MemoryStream, FileStream
System::IO::CompressionGZipStream, DeflateStream, ZipArchive
System::IO::IsolatedStorageIsolatedStorageFile, IsolatedStorageFileStream
System::IO::HashingXxHash32, XxHash64, Crc32
System::TextStringBuilder, Encoding, ASCIIEncoding, UTF8Encoding
System::Text::JsonJsonDocument, JsonSerializer (backed by nlohmann/json)
System::XmlXmlReader, XmlWriter (backed by tinyxml2)
System::Xml::LinqXDocument, XElement, XAttribute, XName
System::ThreadingThread, Mutex, Monitor, CancellationToken, Timer, etc.
System::Threading::TasksTask<T>, ValueTask, Parallel
System::NumericsVector2/3/4, Matrix3x2/4x4, Quaternion, Plane, BigInteger
System::GlobalizationCultureInfo, DateTime formatting, calendars
System::DiagnosticsDebug, Debugger, Stopwatch, StackTrace
System::Net::SocketsTcpClient, UdpClient, NetworkStream

Key Architectural Decisions

1. std::string as the String Type

C# string maps directly to std::string in C++. There is no custom String object type. System::String is a static utility class with helper methods (Split, Format, IsNullOrEmpty, etc.) — it cannot be instantiated.

2. std::vector<T> as the Array Type

C# T[] maps to std::vector<T>. System::Array is a static template utility class with helpers (Sort, Copy, Resize, IndexOf, etc.) — not a concrete array type.

3. No Garbage Collector

Memory is managed via C++ RAII and smart pointers (std::shared_ptr, std::unique_ptr). There is no GC. The System::GC class exists as a stub/no-op only.

4. C++ Exceptions = .NET Exceptions

System::Exception inherits from std::exception, so it integrates naturally with C++ exception handling. All sharp-runtime exceptions are real C++ exceptions that can be caught with catch(const System::Exception& e) or catch(const std::exception& e).

5. EventHandler Combines Delegate + Event

C++ has no event keyword. System::EventHandler<T> combines both the delegate signature and the subscriber list. It supports operator+= for subscription (mirroring C# syntax) and Raise() / Invoke() for firing.

6. Property Macros

C++ has no property syntax. sharp-runtime provides macros (DDATA, DGETTER, DGETTERSTATIC) in include/SharpRuntime/Prop.hpp that generate getXxxProperty() / setXxxProperty() methods backed by private member fields.

7. Header + Implementation Split

Complex types use .hpp declaration + .cpp body. Simple types (enums, small structs, header-only templates) are header-only. CMake auto-discovers all .cpp files via GLOB_RECURSE.

8. Platform Guards in .cpp Only

POSIX includes (<unistd.h>, <sys/socket.h>, etc.) must not appear in public .hpp headers. Platform-specific code lives in .cpp files behind #ifdef _WIN32 / #elif defined(__EMSCRIPTEN__) / #else guards.

9. Immutable Collections Use shared_ptr

Immutable collection types (ImmutableArray, ImmutableList, etc.) are backed by shared_ptr<const std::container<T>>.

10. Namespace Syntax

The project uses C++17 nested namespace syntax:

namespace System::Collections::Generic {
    template<typename T>
    class List { ... };
}

Object Model

The base class for all non-primitive types is System::Object. It provides:

The GetTypeName() method is assisted by the macros GetTypeNameHPP() and GetTypeNameCPP(CLASS, NAME) defined in include/System/Object.hpp.

Summary Diagram

System::Object  (base class, virtual dispatch)
  ├── System::Exception
  │     ├── System::SystemException
  │     │     ├── System::ArgumentException
  │     │     │     ├── ArgumentNullException
  │     │     │     └── ArgumentOutOfRangeException
  │     │     ├── System::InvalidOperationException
  │     │     ├── System::NullReferenceException
  │     │     ├── System::IndexOutOfRangeException
  │     │     ├── System::IO::IOException
  │     │     │     ├── FileNotFoundException
  │     │     │     ├── DirectoryNotFoundException
  │     │     │     └── EndOfStreamException
  │     │     └── ... (many more)
  │     └── System::ApplicationException
  ├── System::EventArgs
  └── ... (other non-exception System types)