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:
| Namespace | Description |
|---|---|
SharpRuntime | Primitive type aliases (intcs, bytecs, etc.) and utility macros |
SharpRuntime::Storage | Storage path utilities for isolated storage |
System | Core types: Object, String, Array, Exception, Math, DateTime, etc. |
System::Collections | Non-generic collections: ArrayList, Hashtable, BitArray |
System::Collections::Generic | Generic: List<T>, Dictionary<K,V>, HashSet<T>, Queue<T>, etc. |
System::Collections::Concurrent | Thread-safe collections |
System::Collections::Immutable | Immutable collection types |
System::Collections::ObjectModel | Collection base classes: Collection<T>, ObservableCollection<T> |
System::IO | Stream, File, Directory, Path, MemoryStream, FileStream |
System::IO::Compression | GZipStream, DeflateStream, ZipArchive |
System::IO::IsolatedStorage | IsolatedStorageFile, IsolatedStorageFileStream |
System::IO::Hashing | XxHash32, XxHash64, Crc32 |
System::Text | StringBuilder, Encoding, ASCIIEncoding, UTF8Encoding |
System::Text::Json | JsonDocument, JsonSerializer (backed by nlohmann/json) |
System::Xml | XmlReader, XmlWriter (backed by tinyxml2) |
System::Xml::Linq | XDocument, XElement, XAttribute, XName |
System::Threading | Thread, Mutex, Monitor, CancellationToken, Timer, etc. |
System::Threading::Tasks | Task<T>, ValueTask, Parallel |
System::Numerics | Vector2/3/4, Matrix3x2/4x4, Quaternion, Plane, BigInteger |
System::Globalization | CultureInfo, DateTime formatting, calendars |
System::Diagnostics | Debug, Debugger, Stopwatch, StackTrace |
System::Net::Sockets | TcpClient, 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:
virtual std::string ToString() constvirtual bool Equals(const Object*) constvirtual int GetHashCode() constvirtual const std::string& GetTypeName() const = 0— pure virtual; must be overridden
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)