-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Implement native terminal drivers.
- Loading branch information
Showing
16 changed files
with
288 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/out | ||
*.user | ||
.clangd | ||
.idea | ||
.vs | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
-err | ||
# TODO: https://github.com/ziglang/zig/issues/13385 | ||
# TODO: https://github.com/ziglang/zig/issues/15398 | ||
#-err | ||
-nr:false | ||
-tl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
namespace Vezel.Cathode.Native; | ||
|
||
internal static unsafe partial class TerminalInterop | ||
{ | ||
public enum TerminalException | ||
{ | ||
None, | ||
ArgumentOutOfRange, | ||
PlatformNotSupported, | ||
TerminalNotAttached, | ||
TerminalConfiguration, | ||
Terminal, | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
public struct TerminalResult | ||
{ | ||
public TerminalException Exception; | ||
|
||
public sbyte* Message; | ||
|
||
public int Error; | ||
} | ||
|
||
private const string Library = "Vezel.Cathode.Native"; | ||
|
||
static TerminalInterop() | ||
{ | ||
NativeLibrary.SetDllImportResolver( | ||
#pragma warning disable CS0436 | ||
typeof(ThisAssembly).Assembly, | ||
#pragma warning restore CS0436 | ||
static (name, asm, paths) => | ||
{ | ||
// First try the normal search algorithm that takes into account the application's configuration and | ||
// static dependency information. | ||
if (NativeLibrary.TryLoad(name, asm, paths, out var handle)) | ||
return handle; | ||
|
||
// If someone is trying to load some unknown library through our assembly, at this point, there is | ||
// nothing more that we can do. | ||
if (name != Library) | ||
return 0; | ||
|
||
// It is now likely that someone is trying to use Cathode without static dependency information, so the | ||
// runtime has no idea how to find Vezel.Cathode.Native. In this case, it is likely to either sit right | ||
// next to Vezel.Cathode.dll, or in runtimes/<rid>/native. | ||
|
||
var directory = AppContext.BaseDirectory; | ||
var fileName = OperatingSystem.IsWindows() | ||
? $"{name}.dll" | ||
: OperatingSystem.IsMacOS() | ||
? $"lib{name}.dylib" | ||
: $"lib{name}.so"; | ||
|
||
bool TryLoad(out nint handle, params string[] paths) | ||
{ | ||
return NativeLibrary.TryLoad(Path.Combine([directory, .. paths, fileName]), out handle); | ||
} | ||
|
||
return TryLoad(out handle) | ||
? handle | ||
: TryLoad(out handle, "runtimes", RuntimeInformation.RuntimeIdentifier, "native") | ||
? handle | ||
: 0; | ||
}); | ||
} | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_initialize")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial void Initialize(); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_set_mode")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial TerminalResult DriverSetMode( | ||
[MarshalAs(UnmanagedType.U1)] bool raw, [MarshalAs(UnmanagedType.U1)] bool flush); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_query_size")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
[return: MarshalAs(UnmanagedType.U1)] | ||
public static partial bool DriverQuerySize(int* width, int* height); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_generate_signal")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial TerminalResult DriverGenerateSignal(TerminalSignal signal); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_open_standard_io")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial void DriverOpenStandardIO(nuint* @in, nuint* @out, nuint* error); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_open_terminal_io")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial void DriverOpenTerminalIO(nuint* @in, nuint* @out); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_is_valid")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
[return: MarshalAs(UnmanagedType.U1)] | ||
public static partial bool DriverIsValid(nuint handle, [MarshalAs(UnmanagedType.U1)] bool write); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_is_interactive")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
[return: MarshalAs(UnmanagedType.U1)] | ||
public static partial bool DriverIsInteractive(nuint handle); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_read")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial TerminalResult DriverRead(nuint handle, byte* buffer, int length, int* progress); | ||
|
||
[LibraryImport(Library, EntryPoint = "cathode_driver_write")] | ||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] | ||
public static partial TerminalResult DriverWrite(nuint handle, byte* buffer, int length, int* progress); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
namespace Vezel.Cathode; | ||
|
||
// Keep in sync with src/native/driver.h. | ||
public enum TerminalSignal | ||
{ | ||
Close, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
#define atomic _Atomic | ||
#define nonnull _Nonnull | ||
#define nullable _Nullable | ||
|
||
#if defined(ZIG_OS_WINDOWS) | ||
# define CATHODE_API [[gnu::dllexport]] | ||
#else | ||
# define CATHODE_API [[gnu::visibility("default")]] | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "common.h" | ||
|
||
void cathode_initialize(void) | ||
{ | ||
// This is just used to ensure that the library is loaded. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#pragma once | ||
|
||
CATHODE_API void cathode_initialize(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#if !defined(ZIG_OS_WINDOWS) | ||
|
||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <poll.h> | ||
#include <signal.h> | ||
#include <sys/ioctl.h> | ||
#include <termios.h> | ||
#include <unistd.h> | ||
|
||
#include "driver.h" | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#if defined(ZIG_OS_WINDOWS) | ||
|
||
#include <windows.h> | ||
|
||
#include "driver.h" | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#pragma once | ||
|
||
typedef size_t TerminalHandle; | ||
|
||
typedef enum { | ||
TerminalException_None, | ||
TerminalException_ArgumentOutOfRange, | ||
TerminalException_PlatformNotSupported, | ||
TerminalException_TerminalNotAttached, | ||
TerminalException_TerminalConfiguration, | ||
TerminalException_Terminal, | ||
} TerminalException; | ||
|
||
typedef struct { | ||
TerminalException exception; | ||
const char *nullable message; | ||
int32_t error; | ||
} TerminalResult; | ||
|
||
// Keep in sync with src/core/TerminalSignal.cs (public API). | ||
typedef enum { | ||
TerminalSignal_Close, | ||
TerminalSignal_Interrupt, | ||
TerminalSignal_Quit, | ||
TerminalSignal_Terminate, | ||
} TerminalSignal; | ||
|
||
CATHODE_API TerminalResult cathode_driver_set_mode(bool raw, bool flush); | ||
|
||
CATHODE_API bool cathode_driver_query_size(int32_t *nonnull width, int32_t *nonnull height); | ||
|
||
CATHODE_API TerminalResult cathode_driver_generate_signal(TerminalSignal signal); | ||
|
||
CATHODE_API void cathode_driver_open_standard_io( | ||
TerminalHandle *nonnull in, TerminalHandle *nonnull out, TerminalHandle *nonnull error); | ||
|
||
CATHODE_API void cathode_driver_open_terminal_io(TerminalHandle *nonnull in, TerminalHandle *nonnull out); | ||
|
||
CATHODE_API bool cathode_driver_is_valid(TerminalHandle handle, bool write); | ||
|
||
CATHODE_API bool cathode_driver_is_interactive(TerminalHandle handle); | ||
|
||
CATHODE_API TerminalResult cathode_driver_read( | ||
TerminalHandle handle, uint8_t *nullable buffer, int32_t length, int32_t *nonnull progress); | ||
|
||
CATHODE_API TerminalResult cathode_driver_write( | ||
TerminalHandle handle, const uint8_t *nullable buffer, int32_t length, int32_t *nonnull progress); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<Project Sdk="Vezel.Zig.Sdk"> | ||
<PropertyGroup> | ||
<AssemblyName>Vezel.Cathode.Native</AssemblyName> | ||
<DefineConstants> | ||
$(DefineConstants); | ||
_GNU_SOURCE; | ||
_UNICODE; | ||
UNICODE; | ||
WIN32_LEAN_AND_MEAN | ||
</DefineConstants> | ||
<!-- TODO: Remove when -err is re-enabled in Directory.Build.rsp. --> | ||
<MSBuildTreatWarningsAsErrors>false</MSBuildTreatWarningsAsErrors> | ||
<!-- TODO: https://github.com/vezel-dev/zig-sdk/issues/83 --> | ||
<RuntimeIdentifiers> | ||
linux-arm; | ||
linux-arm64; | ||
linux-x64; | ||
osx-arm64; | ||
osx-x64; | ||
win-arm64; | ||
win-x86; | ||
win-x64 | ||
</RuntimeIdentifiers> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PreludeHeader Include="cathode.h" /> | ||
</ItemGroup> | ||
|
||
<Target Name="_GetNativeLibrary" | ||
Returns="@(_NativeLibrary)"> | ||
<ItemGroup> | ||
<_NativeLibrary Include="$(TargetPath)" | ||
RuntimeIdentifier="$(RuntimeIdentifier)" /> | ||
</ItemGroup> | ||
</Target> | ||
|
||
<Target Name="_GetNativeLibraries" | ||
Returns="@(_NativeLibrary)"> | ||
<ItemGroup> | ||
<_RuntimeIdentifiers Include="$(RuntimeIdentifiers)" /> | ||
<_Projects Include="$(MSBuildProjectFullPath)" | ||
Properties="RuntimeIdentifier=%(_RuntimeIdentifiers.Identity)" /> | ||
</ItemGroup> | ||
|
||
<MSBuild Projects="@(_Projects)" | ||
Targets="_GetNativeLibrary" | ||
BuildInParallel="$(BuildInParallel)"> | ||
<Output TaskParameter="TargetOutputs" | ||
ItemName="_NativeLibrary" /> | ||
</MSBuild> | ||
</Target> | ||
</Project> |