generate most of the c# binding with a fork of csbindgen

This commit is contained in:
Vinzenz Schroeter 2024-10-19 14:21:50 +02:00
parent 91cc982394
commit 67969d5b43
34 changed files with 791 additions and 819 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "crates/servicepoint_csbindgen"]
path = crates/servicepoint_csbindgen
url = https://github.com/kaesaecracker/servicepoint_csbindgen.git

19
Cargo.lock generated
View file

@ -208,6 +208,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "convert_case"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "cpufeatures"
version = "0.2.14"
@ -239,9 +248,8 @@ dependencies = [
[[package]]
name = "csbindgen"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c26b9831049b947d154bba920e4124053def72447be6fb106a96f483874b482a"
dependencies = [
"convert_case",
"regex",
"syn",
]
@ -636,6 +644,7 @@ dependencies = [
name = "servicepoint_binding_cs"
version = "0.10.0"
dependencies = [
"convert_case",
"csbindgen",
"servicepoint",
"servicepoint_binding_c",
@ -778,6 +787,12 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "utf-8"
version = "0.7.6"

View file

@ -1,8 +1,11 @@
[workspace]
resolver = "2"
members = [
"crates/*",
"crates/servicepoint_binding_c/examples/lang_c"
"crates/servicepoint",
"crates/servicepoint_binding_c",
"crates/servicepoint_binding_c/examples/lang_c",
"crates/servicepoint_binding_cs",
"crates/servicepoint_csbindgen/csbindgen"
]
[workspace.package]

View file

@ -31,11 +31,8 @@ fn main() {
let mut filled_grid = Bitmap::max_sized();
filled_grid.fill(true);
let command = BitmapLinearWin(
Origin::ZERO,
filled_grid,
CompressionCode::Lzma,
);
let command =
BitmapLinearWin(Origin::ZERO, filled_grid, CompressionCode::Lzma);
connection.send(command).expect("send failed");
}

View file

@ -2,9 +2,9 @@
//!
//! prefix `sp_bitvec_`
use std::ptr::NonNull;
use crate::SPByteSlice;
use servicepoint::bitvec::prelude::{BitVec, Msb0};
use std::ptr::NonNull;
/// A vector of bits
///

View file

@ -2,8 +2,8 @@
//!
//! prefix `sp_bitmap_`
use std::ptr::NonNull;
use servicepoint::{DataRef, Grid};
use std::ptr::NonNull;
use crate::byte_slice::SPByteSlice;
@ -43,9 +43,7 @@ pub unsafe extern "C" fn sp_bitmap_new(
width: usize,
height: usize,
) -> NonNull<SPBitmap> {
let result = Box::new(SPBitmap(servicepoint::Bitmap::new(
width, height,
)));
let result = Box::new(SPBitmap(servicepoint::Bitmap::new(width, height)));
NonNull::from(Box::leak(result))
}
@ -80,9 +78,8 @@ pub unsafe extern "C" fn sp_bitmap_load(
) -> NonNull<SPBitmap> {
assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length);
let result = Box::new(SPBitmap(servicepoint::Bitmap::load(
width, height, data,
)));
let result =
Box::new(SPBitmap(servicepoint::Bitmap::load(width, height, data)));
NonNull::from(Box::leak(result))
}

View file

@ -48,9 +48,9 @@ pub unsafe extern "C" fn sp_brightness_grid_new(
width: usize,
height: usize,
) -> NonNull<SPBrightnessGrid> {
let result = Box::new(SPBrightnessGrid(
servicepoint::BrightnessGrid::new(width, height),
));
let result = Box::new(SPBrightnessGrid(servicepoint::BrightnessGrid::new(
width, height,
)));
NonNull::from(Box::leak(result))
}

View file

@ -164,9 +164,8 @@ pub unsafe extern "C" fn sp_command_brightness(
) -> NonNull<SPCommand> {
let brightness =
Brightness::try_from(brightness).expect("invalid brightness");
let result = Box::new(SPCommand(
servicepoint::Command::Brightness(brightness),
));
let result =
Box::new(SPCommand(servicepoint::Command::Brightness(brightness)));
NonNull::from(Box::leak(result))
}
@ -196,9 +195,10 @@ pub unsafe extern "C" fn sp_command_char_brightness(
) -> NonNull<SPCommand> {
assert!(!grid.is_null());
let byte_grid = *Box::from_raw(grid);
let result = Box::new(SPCommand(
servicepoint::Command::CharBrightness(Origin::new(x, y), byte_grid.0),
));
let result = Box::new(SPCommand(servicepoint::Command::CharBrightness(
Origin::new(x, y),
byte_grid.0,
)));
NonNull::from(Box::leak(result))
}
@ -235,13 +235,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinear(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
),
));
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinear(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
}
@ -278,13 +276,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearAnd(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
),
));
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearAnd(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
}
@ -321,13 +317,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearOr(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
),
));
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearOr(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
}
@ -364,13 +358,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearXor(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
),
));
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearXor(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
}
@ -400,9 +392,10 @@ pub unsafe extern "C" fn sp_command_cp437_data(
) -> NonNull<SPCommand> {
assert!(!grid.is_null());
let grid = *Box::from_raw(grid);
let result = Box::new(SPCommand(
servicepoint::Command::Cp437Data(Origin::new(x, y), grid.0),
));
let result = Box::new(SPCommand(servicepoint::Command::Cp437Data(
Origin::new(x, y),
grid.0,
)));
NonNull::from(Box::leak(result))
}
@ -435,15 +428,13 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
) -> NonNull<SPCommand> {
assert!(!bitmap.is_null());
let byte_grid = (*Box::from_raw(bitmap)).0;
let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearWin(
Origin::new(x, y),
byte_grid,
compression_code
.try_into()
.expect("invalid compression code"),
),
));
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearWin(
Origin::new(x, y),
byte_grid,
compression_code
.try_into()
.expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
}

View file

@ -2,9 +2,9 @@
//!
//! prefix `sp_cp437_grid_`
use std::ptr::NonNull;
use crate::SPByteSlice;
use servicepoint::{DataRef, Grid};
use std::ptr::NonNull;
/// A C-wrapper for grid containing codepage 437 characters.
///
@ -41,9 +41,8 @@ pub unsafe extern "C" fn sp_cp437_grid_new(
width: usize,
height: usize,
) -> NonNull<SPCp437Grid> {
let result = Box::new(SPCp437Grid(
servicepoint::Cp437Grid::new(width, height),
));
let result =
Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(width, height)));
NonNull::from(Box::leak(result))
}
@ -73,9 +72,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
) -> NonNull<SPCp437Grid> {
assert!(data.is_null());
let data = std::slice::from_raw_parts(data, data_length);
let result = Box::new(SPCp437Grid(
servicepoint::Cp437Grid::load(width, height, data),
));
let result = Box::new(SPCp437Grid(servicepoint::Cp437Grid::load(
width, height, data,
)));
NonNull::from(Box::leak(result))
}

View file

@ -10,7 +10,7 @@ crate-type = ["cdylib"]
test = false
[build-dependencies]
csbindgen = "1.9.3"
csbindgen = { path = "../servicepoint_csbindgen/csbindgen" }
convert_case = "0.6.0"
[dependencies]

View file

@ -1,49 +0,0 @@
using GroupedNativeMethodsGenerator;
namespace ServicePoint.BindGen;
[GroupedNativeMethods(removePrefix: "sp_bitmap_")]
public static unsafe partial class BitmapNative
{
}
[GroupedNativeMethods(removePrefix: "sp_bitvec_")]
public static unsafe partial class BitVecNative
{
}
[GroupedNativeMethods(removePrefix: "sp_brightness_grid")]
public static unsafe partial class BrightnessGridNative
{
}
[GroupedNativeMethods(removePrefix: "sp_byte_slice")]
public static unsafe partial class ByteSliceNative
{
}
[GroupedNativeMethods(removePrefix: "sp_command_")]
public static unsafe partial class CommandNative
{
}
[GroupedNativeMethods(removePrefix: "sp_connection_")]
public static unsafe partial class ConnectionNative
{
}
[GroupedNativeMethods(removePrefix: "sp_constants_")]
public static unsafe partial class ConstantsNative
{
}
[GroupedNativeMethods(removePrefix: "sp_cp437_grid_")]
public static unsafe partial class Cp437GridNative
{
}
[GroupedNativeMethods(removePrefix: "sp_packet_")]
public static unsafe partial class PacketNative
{
}

View file

@ -1,87 +1,12 @@
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class BitVec : SpNativeInstance<BindGen.BitVec>
public sealed partial class BitVec
{
public static BitVec New(nuint size)
{
unsafe
{
return new BitVec(BitVecNative.sp_bitvec_new(size));
}
}
public static BitVec Load(Span<byte> bytes)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
return new BitVec(BitVecNative.sp_bitvec_load(bytesPtr, (nuint)bytes.Length));
}
}
}
public BitVec Clone()
{
unsafe
{
return new BitVec(Instance->Clone());
}
}
public bool this[nuint index]
{
get
{
unsafe
{
return Instance->Get(index);
}
}
set
{
unsafe
{
Instance->Set(index, value);
}
}
get => Get(index);
set => Set(index, value);
}
public void Fill(bool value)
{
unsafe
{
Instance->Fill(value);
}
}
public nuint Length
{
get
{
unsafe
{
return Instance->Len();
}
}
}
public Span<byte> Data
{
get
{
unsafe
{
return Instance->UnsafeDataRef().AsSpan();
}
}
}
private unsafe BitVec(BindGen.BitVec* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
public Span<byte> Data => UnsafeDataRef().AsSpan();
}

View file

@ -8,14 +8,95 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class BitVecNative
public unsafe sealed partial class BitVec: IDisposable
{
#nullable enable
public BitVec(nuint size) : this(sp_bitvec_new(size)) {}
public static BitVec Load(byte* data, nuint data_length)
{
return new BitVec(BitVec.sp_bitvec_load(data, data_length));
}
public BitVec Clone()
{
return new BitVec(BitVec.sp_bitvec_clone(Instance));
}
public bool Get(nuint index)
{
return BitVec.sp_bitvec_get(Instance, index);
}
public void Set(nuint index, bool value)
{
BitVec.sp_bitvec_set(Instance, index, value);
}
public void Fill(bool value)
{
BitVec.sp_bitvec_fill(Instance, value);
}
public nuint Len()
{
return BitVec.sp_bitvec_len(Instance);
}
public bool IsEmpty()
{
return BitVec.sp_bitvec_is_empty(Instance);
}
public SPByteSlice UnsafeDataRef()
{
return BitVec.sp_bitvec_unsafe_data_ref(Instance);
}
private SPBitVec* _instance;
internal SPBitVec* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private BitVec(SPBitVec* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPBitVec* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
BitVec.sp_bitvec_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~BitVec() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Creates a new [SPBitVec] instance.
///
@ -37,7 +118,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitvec_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bitvec_new(nuint size);
private static extern SPBitVec* sp_bitvec_new(nuint size);
/// <summary>
/// Interpret the data as a series of bits and load then into a new [SPBitVec] instance.
@ -58,7 +139,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitvec_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bitvec_load(byte* data, nuint data_length);
private static extern SPBitVec* sp_bitvec_load(byte* data, nuint data_length);
/// <summary>
/// Clones a [SPBitVec].
@ -79,7 +160,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitvec_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bitvec_clone(BitVec* bit_vec);
private static extern SPBitVec* sp_bitvec_clone(SPBitVec* bit_vec);
/// <summary>
/// Deallocates a [SPBitVec].
@ -97,7 +178,7 @@ namespace ServicePoint.BindGen
/// - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitvec_free(BitVec* bit_vec);
private static extern void sp_bitvec_free(SPBitVec* bit_vec);
/// <summary>
/// Gets the value of a bit from the [SPBitVec].
@ -123,7 +204,7 @@ namespace ServicePoint.BindGen
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_bitvec_get(BitVec* bit_vec, nuint index);
private static extern bool sp_bitvec_get(SPBitVec* bit_vec, nuint index);
/// <summary>
/// Sets the value of a bit in the [SPBitVec].
@ -147,7 +228,7 @@ namespace ServicePoint.BindGen
/// - `bit_vec` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitvec_set(BitVec* bit_vec, nuint index, [MarshalAs(UnmanagedType.U1)] bool value);
private static extern void sp_bitvec_set(SPBitVec* bit_vec, nuint index, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Sets the value of all bits in the [SPBitVec].
@ -169,7 +250,7 @@ namespace ServicePoint.BindGen
/// - `bit_vec` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitvec_fill(BitVec* bit_vec, [MarshalAs(UnmanagedType.U1)] bool value);
private static extern void sp_bitvec_fill(SPBitVec* bit_vec, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Gets the length of the [SPBitVec] in bits.
@ -189,7 +270,7 @@ namespace ServicePoint.BindGen
/// - `bit_vec` points to a valid [SPBitVec]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bitvec_len(BitVec* bit_vec);
private static extern nuint sp_bitvec_len(SPBitVec* bit_vec);
/// <summary>
/// Returns true if length is 0.
@ -210,7 +291,7 @@ namespace ServicePoint.BindGen
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_bitvec_is_empty(BitVec* bit_vec);
private static extern bool sp_bitvec_is_empty(SPBitVec* bit_vec);
/// <summary>
/// Gets an unsafe reference to the data of the [SPBitVec] instance.
@ -232,13 +313,13 @@ namespace ServicePoint.BindGen
/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitvec_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_bitvec_unsafe_data_ref(BitVec* bit_vec);
private static extern SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec* bit_vec);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct BitVec
public unsafe partial struct SPBitVec
{
}

View file

@ -1,100 +1,12 @@
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class Bitmap : SpNativeInstance<BindGen.Bitmap>
public sealed partial class Bitmap
{
public static Bitmap New(nuint width, nuint height)
{
unsafe
{
return new Bitmap(BitmapNative.sp_bitmap_new(width, height));
}
}
public static Bitmap Load(nuint width, nuint height, Span<byte> bytes)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
return new Bitmap(BitmapNative.sp_bitmap_load(width, height, bytesPtr,
(nuint)bytes.Length));
}
}
}
public Bitmap Clone()
{
unsafe
{
return new Bitmap(Instance->Clone());
}
}
public bool this[nuint x, nuint y]
{
get
{
unsafe
{
return Instance->Get(x, y);
}
}
set
{
unsafe
{
Instance->Set(x, y, value);
}
}
get => Get(x, y);
set => Set(x, y, value);
}
public void Fill(bool value)
{
unsafe
{
Instance->Fill(value);
}
}
public nuint Width
{
get
{
unsafe
{
return Instance->Width();
}
}
}
public nuint Height
{
get
{
unsafe
{
return Instance->Height();
}
}
}
public Span<byte> Data
{
get
{
unsafe
{
var slice = Instance->UnsafeDataRef();
return new Span<byte>(slice.start, (int)slice.length);
}
}
}
private unsafe Bitmap(BindGen.Bitmap* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
public Span<byte> Data => UnsafeDataRef().AsSpan();
}

View file

@ -8,14 +8,95 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class BitmapNative
public unsafe sealed partial class Bitmap: IDisposable
{
#nullable enable
public Bitmap(nuint width, nuint height) : this(sp_bitmap_new(width, height)) {}
public static Bitmap Load(nuint width, nuint height, byte* data, nuint data_length)
{
return new Bitmap(Bitmap.sp_bitmap_load(width, height, data, data_length));
}
public Bitmap Clone()
{
return new Bitmap(Bitmap.sp_bitmap_clone(Instance));
}
public bool Get(nuint x, nuint y)
{
return Bitmap.sp_bitmap_get(Instance, x, y);
}
public void Set(nuint x, nuint y, bool value)
{
Bitmap.sp_bitmap_set(Instance, x, y, value);
}
public void Fill(bool value)
{
Bitmap.sp_bitmap_fill(Instance, value);
}
public nuint Width()
{
return Bitmap.sp_bitmap_width(Instance);
}
public nuint Height()
{
return Bitmap.sp_bitmap_height(Instance);
}
public SPByteSlice UnsafeDataRef()
{
return Bitmap.sp_bitmap_unsafe_data_ref(Instance);
}
private SPBitmap* _instance;
internal SPBitmap* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private Bitmap(SPBitmap* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPBitmap* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
Bitmap.sp_bitmap_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~Bitmap() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Creates a new [SPBitmap] with the specified dimensions.
///
@ -38,7 +119,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_new(nuint width, nuint height);
private static extern SPBitmap* sp_bitmap_new(nuint width, nuint height);
/// <summary>
/// Loads a [SPBitmap] with the specified dimensions from the provided data.
@ -65,7 +146,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_load(nuint width, nuint height, byte* data, nuint data_length);
private static extern SPBitmap* sp_bitmap_load(nuint width, nuint height, byte* data, nuint data_length);
/// <summary>
/// Clones a [SPBitmap].
@ -86,7 +167,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_clone(Bitmap* bitmap);
private static extern SPBitmap* sp_bitmap_clone(SPBitmap* bitmap);
/// <summary>
/// Deallocates a [SPBitmap].
@ -104,7 +185,7 @@ namespace ServicePoint.BindGen
/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_free(Bitmap* bitmap);
private static extern void sp_bitmap_free(SPBitmap* bitmap);
/// <summary>
/// Gets the current value at the specified position in the [SPBitmap].
@ -128,7 +209,7 @@ namespace ServicePoint.BindGen
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_bitmap_get(Bitmap* bitmap, nuint x, nuint y);
private static extern bool sp_bitmap_get(SPBitmap* bitmap, nuint x, nuint y);
/// <summary>
/// Sets the value of the specified position in the [SPBitmap].
@ -154,7 +235,7 @@ namespace ServicePoint.BindGen
/// - `bitmap` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_set(Bitmap* bitmap, nuint x, nuint y, [MarshalAs(UnmanagedType.U1)] bool value);
private static extern void sp_bitmap_set(SPBitmap* bitmap, nuint x, nuint y, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Sets the state of all pixels in the [SPBitmap].
@ -176,7 +257,7 @@ namespace ServicePoint.BindGen
/// - `bitmap` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_fill(Bitmap* bitmap, [MarshalAs(UnmanagedType.U1)] bool value);
private static extern void sp_bitmap_fill(SPBitmap* bitmap, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Gets the width in pixels of the [SPBitmap] instance.
@ -196,7 +277,7 @@ namespace ServicePoint.BindGen
/// - `bitmap` points to a valid [SPBitmap]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bitmap_width(Bitmap* bitmap);
private static extern nuint sp_bitmap_width(SPBitmap* bitmap);
/// <summary>
/// Gets the height in pixels of the [SPBitmap] instance.
@ -216,7 +297,7 @@ namespace ServicePoint.BindGen
/// - `bitmap` points to a valid [SPBitmap]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bitmap_height(Bitmap* bitmap);
private static extern nuint sp_bitmap_height(SPBitmap* bitmap);
/// <summary>
/// Gets an unsafe reference to the data of the [SPBitmap] instance.
@ -234,13 +315,13 @@ namespace ServicePoint.BindGen
/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_bitmap_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_bitmap_unsafe_data_ref(Bitmap* bitmap);
private static extern SPByteSlice sp_bitmap_unsafe_data_ref(SPBitmap* bitmap);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Bitmap
public unsafe partial struct SPBitmap
{
}

View file

@ -1,99 +1,12 @@
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class BrightnessGrid : SpNativeInstance<BindGen.BrightnessGrid>
public sealed partial class BrightnessGrid
{
public static BrightnessGrid New(nuint width, nuint height)
{
unsafe
{
return new BrightnessGrid(BrightnessGridNative.sp_brightness_grid_new(width, height));
}
}
public static BrightnessGrid Load(nuint width, nuint height, Span<byte> bytes)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
return new BrightnessGrid(BrightnessGridNative.sp_brightness_grid_load(width, height, bytesPtr,
(nuint)bytes.Length));
}
}
}
public BrightnessGrid Clone()
{
unsafe
{
return new BrightnessGrid(Instance->Clone());
}
}
public byte this[nuint x, nuint y]
{
get
{
unsafe
{
return Instance->Get(x, y);
}
}
set
{
unsafe
{
Instance->Set(x, y, value);
}
}
get => Get(x, y);
set => Set(x, y, value);
}
public void Fill(byte value)
{
unsafe
{
Instance->Fill(value);
}
}
public nuint Width
{
get
{
unsafe
{
return Instance->Width();
}
}
}
public nuint Height
{
get
{
unsafe
{
return Instance->Height();
}
}
}
public Span<byte> Data
{
get
{
unsafe
{
return Instance->UnsafeDataRef().AsSpan();
}
}
}
private unsafe BrightnessGrid(BindGen.BrightnessGrid* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
public Span<byte> Data => UnsafeDataRef().AsSpan();
}

View file

@ -8,7 +8,7 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class BrightnessGridNative
{
@ -19,6 +19,95 @@ namespace ServicePoint.BindGen
public const byte SP_BRIGHTNESS_LEVELS = 12;
}
public unsafe sealed partial class BrightnessGrid: IDisposable
{
#nullable enable
public BrightnessGrid(nuint width, nuint height) : this(sp_brightness_grid_new(width, height)) {}
public static BrightnessGrid Load(nuint width, nuint height, byte* data, nuint data_length)
{
return new BrightnessGrid(BrightnessGrid.sp_brightness_grid_load(width, height, data, data_length));
}
public BrightnessGrid Clone()
{
return new BrightnessGrid(BrightnessGrid.sp_brightness_grid_clone(Instance));
}
public byte Get(nuint x, nuint y)
{
return BrightnessGrid.sp_brightness_grid_get(Instance, x, y);
}
public void Set(nuint x, nuint y, byte value)
{
BrightnessGrid.sp_brightness_grid_set(Instance, x, y, value);
}
public void Fill(byte value)
{
BrightnessGrid.sp_brightness_grid_fill(Instance, value);
}
public nuint Width()
{
return BrightnessGrid.sp_brightness_grid_width(Instance);
}
public nuint Height()
{
return BrightnessGrid.sp_brightness_grid_height(Instance);
}
public SPByteSlice UnsafeDataRef()
{
return BrightnessGrid.sp_brightness_grid_unsafe_data_ref(Instance);
}
private SPBrightnessGrid* _instance;
internal SPBrightnessGrid* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private BrightnessGrid(SPBrightnessGrid* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPBrightnessGrid* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
BrightnessGrid.sp_brightness_grid_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~BrightnessGrid() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Creates a new [SPBrightnessGrid] with the specified dimensions.
///
@ -32,7 +121,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_brightness_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BrightnessGrid* sp_brightness_grid_new(nuint width, nuint height);
private static extern SPBrightnessGrid* sp_brightness_grid_new(nuint width, nuint height);
/// <summary>
/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data.
@ -54,7 +143,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_brightness_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BrightnessGrid* sp_brightness_grid_load(nuint width, nuint height, byte* data, nuint data_length);
private static extern SPBrightnessGrid* sp_brightness_grid_load(nuint width, nuint height, byte* data, nuint data_length);
/// <summary>
/// Clones a [SPBrightnessGrid].
@ -79,7 +168,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_brightness_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BrightnessGrid* sp_brightness_grid_clone(BrightnessGrid* brightness_grid);
private static extern SPBrightnessGrid* sp_brightness_grid_clone(SPBrightnessGrid* brightness_grid);
/// <summary>
/// Deallocates a [SPBrightnessGrid].
@ -101,7 +190,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_brightness_grid_free(BrightnessGrid* brightness_grid);
private static extern void sp_brightness_grid_free(SPBrightnessGrid* brightness_grid);
/// <summary>
/// Gets the current value at the specified position.
@ -126,7 +215,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` is not written to concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern byte sp_brightness_grid_get(BrightnessGrid* brightness_grid, nuint x, nuint y);
private static extern byte sp_brightness_grid_get(SPBrightnessGrid* brightness_grid, nuint x, nuint y);
/// <summary>
/// Sets the value of the specified position in the [SPBrightnessGrid].
@ -153,7 +242,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_brightness_grid_set(BrightnessGrid* brightness_grid, nuint x, nuint y, byte value);
private static extern void sp_brightness_grid_set(SPBrightnessGrid* brightness_grid, nuint x, nuint y, byte value);
/// <summary>
/// Sets the value of all cells in the [SPBrightnessGrid].
@ -176,7 +265,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_brightness_grid_fill(BrightnessGrid* brightness_grid, byte value);
private static extern void sp_brightness_grid_fill(SPBrightnessGrid* brightness_grid, byte value);
/// <summary>
/// Gets the width of the [SPBrightnessGrid] instance.
@ -198,7 +287,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_brightness_grid_width(BrightnessGrid* brightness_grid);
private static extern nuint sp_brightness_grid_width(SPBrightnessGrid* brightness_grid);
/// <summary>
/// Gets the height of the [SPBrightnessGrid] instance.
@ -220,7 +309,7 @@ namespace ServicePoint.BindGen
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_brightness_grid_height(BrightnessGrid* brightness_grid);
private static extern nuint sp_brightness_grid_height(SPBrightnessGrid* brightness_grid);
/// <summary>
/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance.
@ -244,13 +333,13 @@ namespace ServicePoint.BindGen
/// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid* brightness_grid);
private static extern SPByteSlice sp_brightness_grid_unsafe_data_ref(SPBrightnessGrid* brightness_grid);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct BrightnessGrid
public unsafe partial struct SPBrightnessGrid
{
}

View file

@ -8,12 +8,12 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct ByteSlice
public unsafe partial struct SPByteSlice
{
public byte* start;
public nuint length;

View file

@ -1,129 +1,11 @@
using System.Diagnostics.CodeAnalysis;
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class Command : SpNativeInstance<BindGen.Command>
public sealed partial class Command
{
public static bool TryFromPacket(Packet packet, [MaybeNullWhen(false)] out Command command)
{
unsafe
{
var result = CommandNative.sp_command_try_from_packet(packet.Into());
if (result == null)
{
command = null;
return false;
}
command = new Command(result);
return true;
}
return (command = TryFromPacket(packet)) != null;
}
public Command Clone()
{
unsafe
{
return new Command(Instance->Clone());
}
}
public static Command Clear()
{
unsafe
{
return new Command(CommandNative.sp_command_clear());
}
}
public static Command HardReset()
{
unsafe
{
return new Command(CommandNative.sp_command_hard_reset());
}
}
public static Command FadeOut()
{
unsafe
{
return new Command(CommandNative.sp_command_fade_out());
}
}
public static Command Brightness(byte brightness)
{
unsafe
{
return new Command(CommandNative.sp_command_brightness(brightness));
}
}
public static Command CharBrightness(ushort x, ushort y, BrightnessGrid grid)
{
unsafe
{
return new Command(CommandNative.sp_command_char_brightness(x, y, grid.Into()));
}
}
public static Command BitmapLinear(ushort offset, BitVec bitVec, CompressionCode compressionCode)
{
unsafe
{
return new Command(
CommandNative.sp_command_bitmap_linear(offset, bitVec.Into(), compressionCode));
}
}
public static Command BitmapLinearAnd(ushort offset, BitVec bitVec, CompressionCode compressionCode)
{
unsafe
{
return new Command(
CommandNative.sp_command_bitmap_linear_and(offset, bitVec.Into(), compressionCode));
}
}
public static Command BitmapLinearOr(ushort offset, BitVec bitVec, CompressionCode compressionCode)
{
unsafe
{
return new Command(
CommandNative.sp_command_bitmap_linear_or(offset, bitVec.Into(), compressionCode));
}
}
public static Command BitmapLinearXor(ushort offset, BitVec bitVec, CompressionCode compressionCode)
{
unsafe
{
return new Command(
CommandNative.sp_command_bitmap_linear_xor(offset, bitVec.Into(), compressionCode));
}
}
public static Command BitmapLinearWin(ushort x, ushort y, Bitmap bitmap, CompressionCode compression)
{
unsafe
{
return new Command(CommandNative.sp_command_bitmap_linear_win(x, y, bitmap.Into(), compression));
}
}
public static Command Cp437Data(ushort x, ushort y, Cp437Grid byteGrid)
{
unsafe
{
return new Command(CommandNative.sp_command_cp437_data(x, y, byteGrid.Into()));
}
}
private unsafe Command(BindGen.Command* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
}

View file

@ -8,14 +8,119 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class CommandNative
public unsafe sealed partial class Command: IDisposable
{
#nullable enable
public static Command? TryFromPacket(Packet packet)
{
var native = Command.sp_command_try_from_packet(packet.Instance);
return native == null ? null : new Command(native);
}
public Command Clone()
{
return new Command(Command.sp_command_clone(Instance));
}
public static Command Clear()
{
return new Command(Command.sp_command_clear());
}
public static Command HardReset()
{
return new Command(Command.sp_command_hard_reset());
}
public static Command FadeOut()
{
return new Command(Command.sp_command_fade_out());
}
public static Command Brightness(byte brightness)
{
return new Command(Command.sp_command_brightness(brightness));
}
public static Command CharBrightness(nuint x, nuint y, BrightnessGrid grid)
{
return new Command(Command.sp_command_char_brightness(x, y, grid.Instance));
}
public static Command BitmapLinear(nuint offset, BitVec bit_vec, CompressionCode compression)
{
return new Command(Command.sp_command_bitmap_linear(offset, bit_vec.Instance, compression));
}
public static Command BitmapLinearAnd(nuint offset, BitVec bit_vec, CompressionCode compression)
{
return new Command(Command.sp_command_bitmap_linear_and(offset, bit_vec.Instance, compression));
}
public static Command BitmapLinearOr(nuint offset, BitVec bit_vec, CompressionCode compression)
{
return new Command(Command.sp_command_bitmap_linear_or(offset, bit_vec.Instance, compression));
}
public static Command BitmapLinearXor(nuint offset, BitVec bit_vec, CompressionCode compression)
{
return new Command(Command.sp_command_bitmap_linear_xor(offset, bit_vec.Instance, compression));
}
public static Command Cp437Data(nuint x, nuint y, Cp437Grid grid)
{
return new Command(Command.sp_command_cp437_data(x, y, grid.Instance));
}
public static Command BitmapLinearWin(nuint x, nuint y, Bitmap bitmap, CompressionCode compression_code)
{
return new Command(Command.sp_command_bitmap_linear_win(x, y, bitmap.Instance, compression_code));
}
private SPCommand* _instance;
internal SPCommand* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private Command(SPCommand* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPCommand* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
Command.sp_command_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~Command() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Tries to turn a [SPPacket] into a [SPCommand].
///
@ -38,7 +143,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_try_from_packet(Packet* packet);
private static extern SPCommand* sp_command_try_from_packet(SPPacket* packet);
/// <summary>
/// Clones a [SPCommand] instance.
@ -59,7 +164,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clone(Command* command);
private static extern SPCommand* sp_command_clone(SPCommand* command);
/// <summary>
/// Set all pixels to the off state.
@ -82,7 +187,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clear();
private static extern SPCommand* sp_command_clear();
/// <summary>
/// Kills the udp daemon on the display, which usually results in a restart.
@ -99,7 +204,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_hard_reset", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_hard_reset();
private static extern SPCommand* sp_command_hard_reset();
/// <summary>
/// A yet-to-be-tested command.
@ -114,7 +219,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_fade_out", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_fade_out();
private static extern SPCommand* sp_command_fade_out();
/// <summary>
/// Set the brightness of all tiles to the same value.
@ -133,7 +238,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_brightness(byte brightness);
private static extern SPCommand* sp_command_brightness(byte brightness);
/// <summary>
/// Set the brightness of individual tiles in a rectangular area of the display.
@ -156,7 +261,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* grid);
private static extern SPCommand* sp_command_char_brightness(nuint x, nuint y, SPBrightnessGrid* grid);
/// <summary>
/// Set pixel data starting at the pixel offset on screen.
@ -186,7 +291,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear(nuint offset, BitVec* bit_vec, CompressionCode compression);
private static extern SPCommand* sp_command_bitmap_linear(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an and-mask starting at the offset.
@ -216,7 +321,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_and(nuint offset, BitVec* bit_vec, CompressionCode compression);
private static extern SPCommand* sp_command_bitmap_linear_and(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an or-mask starting at the offset.
@ -246,7 +351,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_or(nuint offset, BitVec* bit_vec, CompressionCode compression);
private static extern SPCommand* sp_command_bitmap_linear_or(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to a xor-mask starting at the offset.
@ -276,7 +381,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_xor(nuint offset, BitVec* bit_vec, CompressionCode compression);
private static extern SPCommand* sp_command_bitmap_linear_xor(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Show text on the screen.
@ -299,7 +404,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_cp437_data(nuint x, nuint y, Cp437Grid* grid);
private static extern SPCommand* sp_command_cp437_data(nuint x, nuint y, SPCp437Grid* grid);
/// <summary>
/// Sets a window of pixels to the specified values.
@ -324,7 +429,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_win(nuint x, nuint y, Bitmap* bitmap, CompressionCode compression_code);
private static extern SPCommand* sp_command_bitmap_linear_win(nuint x, nuint y, SPBitmap* bitmap, CompressionCode compression_code);
/// <summary>
/// Deallocates a [SPCommand].
@ -349,13 +454,13 @@ namespace ServicePoint.BindGen
/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_command_free(Command* command);
private static extern void sp_command_free(SPCommand* command);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Command
public unsafe partial struct SPCommand
{
}

View file

@ -1,40 +1,21 @@
using System.Text;
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class Connection : SpNativeInstance<BindGen.Connection>
public sealed partial class Connection
{
public static Connection Open(string host)
public static Connection? Open(string host)
{
unsafe
{
fixed (byte* bytePtr = Encoding.UTF8.GetBytes(host))
{
return new Connection(ConnectionNative.sp_connection_open(bytePtr));
return Open(bytePtr);
}
}
}
public bool Send(Packet packet)
{
unsafe
{
return Instance->SendPacket(packet.Into());
}
}
public bool Send(Packet packet) => SendPacket(packet);
public bool Send(Command command)
{
unsafe
{
return Instance->SendCommand(command.Into());
}
}
private protected override unsafe void Free() => Instance->Free();
private unsafe Connection(BindGen.Connection* instance) : base(instance)
{
}
public bool Send(Command command) => SendCommand(command);
}

View file

@ -8,14 +8,69 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class ConnectionNative
public unsafe sealed partial class Connection: IDisposable
{
#nullable enable
public static Connection? Open(byte* host)
{
var native = Connection.sp_connection_open(host);
return native == null ? null : new Connection(native);
}
public bool SendPacket(Packet packet)
{
return Connection.sp_connection_send_packet(Instance, packet.Instance);
}
public bool SendCommand(Command command)
{
return Connection.sp_connection_send_command(Instance, command.Instance);
}
private SPConnection* _instance;
internal SPConnection* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private Connection(SPConnection* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPConnection* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
Connection.sp_connection_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~Connection() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Creates a new instance of [SPConnection].
///
@ -33,7 +88,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_connection_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_open", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Connection* sp_connection_open(byte* host);
private static extern SPConnection* sp_connection_open(byte* host);
/// <summary>
/// Sends a [SPPacket] to the display using the [SPConnection].
@ -57,7 +112,7 @@ namespace ServicePoint.BindGen
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_send_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_connection_send_packet(Connection* connection, Packet* packet);
private static extern bool sp_connection_send_packet(SPConnection* connection, SPPacket* packet);
/// <summary>
/// Sends a [SPCommand] to the display using the [SPConnection].
@ -81,7 +136,7 @@ namespace ServicePoint.BindGen
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_send_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_connection_send_command(Connection* connection, Command* command);
private static extern bool sp_connection_send_command(SPConnection* connection, SPCommand* command);
/// <summary>
/// Closes and deallocates a [SPConnection].
@ -98,13 +153,13 @@ namespace ServicePoint.BindGen
/// - `connection` is not used concurrently or after this call
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_connection_free(Connection* connection);
private static extern void sp_connection_free(SPConnection* connection);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Connection
public unsafe partial struct SPConnection
{
}

View file

@ -1,5 +1,3 @@
using ServicePoint.BindGen;
namespace ServicePoint;
public static class Constants

View file

@ -8,7 +8,7 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class ConstantsNative
{
@ -23,6 +23,7 @@ namespace ServicePoint.BindGen
}
public enum CompressionCode : ushort
{
Uncompressed = 0,

View file

@ -1,61 +1,20 @@
using System.Text;
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
public sealed partial class Cp437Grid
{
public static Cp437Grid New(nuint width, nuint height)
{
unsafe
{
return new Cp437Grid(Cp437GridNative.sp_cp437_grid_new(width, height));
}
}
public static Cp437Grid Load(nuint width, nuint height, Span<byte> bytes)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
return new Cp437Grid(Cp437GridNative.sp_cp437_grid_load(width, height, bytesPtr,
(nuint)bytes.Length));
}
}
}
public Cp437Grid Clone()
{
unsafe
{
return new Cp437Grid(Instance->Clone());
}
}
public byte this[nuint x, nuint y]
{
get
{
unsafe
{
return Instance->Get(x, y);
}
}
set
{
unsafe
{
Instance->Set(x, y, value);
}
}
get => Get(x, y);
set => Set(x, y, value);
}
public string this[nuint y]
{
set
{
var width = Width;
var width = Width();
ArgumentOutOfRangeException.ThrowIfGreaterThan((nuint)value.Length, width);
nuint x = 0;
@ -69,7 +28,8 @@ public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
get
{
var sb = new StringBuilder();
for (nuint x = 0; x < Width; x++)
var width = Width();
for (nuint x = 0; x < width; x++)
{
var val = this[x, y];
if (val == 0)
@ -81,50 +41,5 @@ public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
}
}
public void Fill(byte value)
{
unsafe
{
Instance->Fill(value);
}
}
public nuint Width
{
get
{
unsafe
{
return Instance->Width();
}
}
}
public nuint Height
{
get
{
unsafe
{
return Instance->Height();
}
}
}
public Span<byte> Data
{
get
{
unsafe
{
return Instance->UnsafeDataRef().AsSpan();
}
}
}
private unsafe Cp437Grid(BindGen.Cp437Grid* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
public Span<byte> Data => UnsafeDataRef().AsSpan();
}

View file

@ -8,14 +8,95 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class Cp437GridNative
public unsafe sealed partial class Cp437Grid: IDisposable
{
#nullable enable
public Cp437Grid(nuint width, nuint height) : this(sp_cp437_grid_new(width, height)) {}
public static Cp437Grid Load(nuint width, nuint height, byte* data, nuint data_length)
{
return new Cp437Grid(Cp437Grid.sp_cp437_grid_load(width, height, data, data_length));
}
public Cp437Grid Clone()
{
return new Cp437Grid(Cp437Grid.sp_cp437_grid_clone(Instance));
}
public byte Get(nuint x, nuint y)
{
return Cp437Grid.sp_cp437_grid_get(Instance, x, y);
}
public void Set(nuint x, nuint y, byte value)
{
Cp437Grid.sp_cp437_grid_set(Instance, x, y, value);
}
public void Fill(byte value)
{
Cp437Grid.sp_cp437_grid_fill(Instance, value);
}
public nuint Width()
{
return Cp437Grid.sp_cp437_grid_width(Instance);
}
public nuint Height()
{
return Cp437Grid.sp_cp437_grid_height(Instance);
}
public SPByteSlice UnsafeDataRef()
{
return Cp437Grid.sp_cp437_grid_unsafe_data_ref(Instance);
}
private SPCp437Grid* _instance;
internal SPCp437Grid* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private Cp437Grid(SPCp437Grid* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPCp437Grid* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
Cp437Grid.sp_cp437_grid_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~Cp437Grid() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Creates a new [SPCp437Grid] with the specified dimensions.
///
@ -29,7 +110,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_cp437_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Cp437Grid* sp_cp437_grid_new(nuint width, nuint height);
private static extern SPCp437Grid* sp_cp437_grid_new(nuint width, nuint height);
/// <summary>
/// Loads a [SPCp437Grid] with the specified dimensions from the provided data.
@ -51,7 +132,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_cp437_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Cp437Grid* sp_cp437_grid_load(nuint width, nuint height, byte* data, nuint data_length);
private static extern SPCp437Grid* sp_cp437_grid_load(nuint width, nuint height, byte* data, nuint data_length);
/// <summary>
/// Clones a [SPCp437Grid].
@ -72,7 +153,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_cp437_grid_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Cp437Grid* sp_cp437_grid_clone(Cp437Grid* cp437_grid);
private static extern SPCp437Grid* sp_cp437_grid_clone(SPCp437Grid* cp437_grid);
/// <summary>
/// Deallocates a [SPCp437Grid].
@ -90,7 +171,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_cp437_grid_free(Cp437Grid* cp437_grid);
private static extern void sp_cp437_grid_free(SPCp437Grid* cp437_grid);
/// <summary>
/// Gets the current value at the specified position.
@ -113,7 +194,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` is not written to concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern byte sp_cp437_grid_get(Cp437Grid* cp437_grid, nuint x, nuint y);
private static extern byte sp_cp437_grid_get(SPCp437Grid* cp437_grid, nuint x, nuint y);
/// <summary>
/// Sets the value of the specified position in the [SPCp437Grid].
@ -139,7 +220,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_cp437_grid_set(Cp437Grid* cp437_grid, nuint x, nuint y, byte value);
private static extern void sp_cp437_grid_set(SPCp437Grid* cp437_grid, nuint x, nuint y, byte value);
/// <summary>
/// Sets the value of all cells in the [SPCp437Grid].
@ -161,7 +242,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_cp437_grid_fill(Cp437Grid* cp437_grid, byte value);
private static extern void sp_cp437_grid_fill(SPCp437Grid* cp437_grid, byte value);
/// <summary>
/// Gets the width of the [SPCp437Grid] instance.
@ -181,7 +262,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` points to a valid [SPCp437Grid]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_cp437_grid_width(Cp437Grid* cp437_grid);
private static extern nuint sp_cp437_grid_width(SPCp437Grid* cp437_grid);
/// <summary>
/// Gets the height of the [SPCp437Grid] instance.
@ -201,7 +282,7 @@ namespace ServicePoint.BindGen
/// - `cp437_grid` points to a valid [SPCp437Grid]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_cp437_grid_height(Cp437Grid* cp437_grid);
private static extern nuint sp_cp437_grid_height(SPCp437Grid* cp437_grid);
/// <summary>
/// Gets an unsafe reference to the data of the [SPCp437Grid] instance.
@ -221,13 +302,13 @@ namespace ServicePoint.BindGen
/// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid* cp437_grid);
private static extern SPByteSlice sp_cp437_grid_unsafe_data_ref(SPCp437Grid* cp437_grid);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Cp437Grid
public unsafe partial struct SPCp437Grid
{
}

View file

@ -1,36 +1,18 @@
using System.Diagnostics.CodeAnalysis;
using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class Packet : SpNativeInstance<BindGen.Packet>
public sealed partial class Packet
{
public static Packet FromCommand(Command command)
{
unsafe
{
return new Packet(PacketNative.sp_packet_from_command(command.Into()));
}
}
public static bool TryFromBytes(Span<byte> bytes, [MaybeNullWhen(false)] out Packet packet)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
var instance = PacketNative.sp_packet_try_load(bytesPtr, (nuint)bytes.Length);
packet = instance == null
? null
: new Packet(instance);
packet = TryLoad(bytesPtr, (nuint)bytes.Length);
return packet != null;
}
}
}
private unsafe Packet(BindGen.Packet* instance) : base(instance)
{
}
private protected override unsafe void Free() => Instance->Free();
}

View file

@ -8,14 +8,69 @@ using System;
using System.Runtime.InteropServices;
namespace ServicePoint.BindGen
namespace ServicePoint
{
public static unsafe partial class PacketNative
public unsafe sealed partial class Packet: IDisposable
{
#nullable enable
public static Packet FromCommand(Command command)
{
return new Packet(Packet.sp_packet_from_command(command.Instance));
}
public static Packet? TryLoad(byte* data, nuint length)
{
var native = Packet.sp_packet_try_load(data, length);
return native == null ? null : new Packet(native);
}
public Packet Clone()
{
return new Packet(Packet.sp_packet_clone(Instance));
}
private SPPacket* _instance;
internal SPPacket* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private Packet(SPPacket* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
internal SPPacket* Into()
{
var instance = Instance;
_instance = null;
return instance;
}
private void Free()
{
if (_instance != null)
Packet.sp_packet_free(Into());
}
public void Dispose()
{
Free();
GC.SuppressFinalize(this);
}
~Packet() => Free();
const string __DllName = "servicepoint_binding_c";
#nullable restore
/// <summary>
/// Turns a [SPCommand] into a [SPPacket].
/// The [SPCommand] gets consumed.
@ -36,7 +91,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_packet_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_packet_from_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Packet* sp_packet_from_command(Command* command);
private static extern SPPacket* sp_packet_from_command(SPCommand* command);
/// <summary>
/// Tries to load a [SPPacket] from the passed array with the specified length.
@ -57,7 +112,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_packet_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_packet_try_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Packet* sp_packet_try_load(byte* data, nuint length);
private static extern SPPacket* sp_packet_try_load(byte* data, nuint length);
/// <summary>
/// Clones a [SPPacket].
@ -78,7 +133,7 @@ namespace ServicePoint.BindGen
/// by explicitly calling `sp_packet_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_packet_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Packet* sp_packet_clone(Packet* packet);
private static extern SPPacket* sp_packet_clone(SPPacket* packet);
/// <summary>
/// Deallocates a [SPPacket].
@ -95,13 +150,13 @@ namespace ServicePoint.BindGen
/// - `packet` is not used concurrently or after this call
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_packet_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_packet_free(Packet* packet);
private static extern void sp_packet_free(SPPacket* packet);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Packet
public unsafe partial struct SPPacket
{
}

View file

@ -52,11 +52,6 @@
</Content>
</ItemGroup>
<!--additional csbindgen code generators-->
<ItemGroup>
<PackageReference Include="csbindgen" Version="1.9.3" PrivateAssets="All"/>
</ItemGroup>
<ItemGroup>
<!-- include link to source code at revision -->
<None Include="../README.md" Pack="true" PackagePath="\"/>

View file

@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using ServicePoint.BindGen;
namespace ServicePoint;
@ -15,7 +14,7 @@ public static class ServicePointExtensions
return Command.TryFromPacket(packet, out command);
}
public unsafe static Span<byte> AsSpan(this ByteSlice slice)
public unsafe static Span<byte> AsSpan(this SPByteSlice slice)
{
return new Span<byte>(slice.start, (int)slice.length);
}

View file

@ -1,51 +0,0 @@
namespace ServicePoint;
public abstract class SpNativeInstance<T>
: IDisposable
where T : unmanaged
{
private unsafe T* _instance;
internal unsafe T* Instance
{
get
{
if (_instance == null)
throw new NullReferenceException("instance is null");
return _instance;
}
}
private protected unsafe SpNativeInstance(T* instance)
{
ArgumentNullException.ThrowIfNull(instance);
_instance = instance;
}
private protected abstract void Free();
internal unsafe T* Into()
{
var instance = _instance;
_instance = null;
return instance;
}
private unsafe void ReleaseUnmanagedResources()
{
if (_instance != null)
Free();
_instance = null;
}
public void Dispose()
{
ReleaseUnmanagedResources();
GC.SuppressFinalize(this);
}
~SpNativeInstance()
{
ReleaseUnmanagedResources();
}
}

View file

@ -17,32 +17,44 @@ fn main() {
for path in &paths {
println!("cargo:rerun-if-changed={}", path.display());
let file: &str = Path::new(path).file_stem().unwrap().to_str().unwrap();
if file == "lib"{
if file == "lib" {
continue;
}
let class = file.to_case(Case::UpperCamel) + "Native";
let class = file.to_case(Case::UpperCamel);
csbindgen::Builder::default()
.input_extern_file(path)
.csharp_class_name(&class)
.csharp_class_name(format!("{class}Native"))
.csharp_dll_name("servicepoint_binding_c")
.csharp_namespace("ServicePoint.BindGen")
.csharp_namespace("ServicePoint")
.csharp_use_nint_types(true)
.csharp_class_accessibility("public")
.csharp_generate_const_filter(|_| true)
.always_included_types(["SPByteSlice", "SPCompressionCode"])
.csharp_group_methods("sp_bitmap_", "Bitmap", "SPBitmap")
.csharp_group_methods("sp_bitvec_", "BitVec", "SPBitVec")
.csharp_group_methods("sp_command_", "Command", "SPCommand")
.csharp_group_methods(
"sp_connection_",
"Connection",
"SPConnection",
)
.csharp_group_methods("sp_cp437_grid_", "Cp437Grid", "SPCp437Grid")
.csharp_group_methods("sp_packet_", "Packet", "SPPacket")
.csharp_group_methods(
"sp_brightness_grid_",
"BrightnessGrid",
"SPBrightnessGrid",
)
.csharp_type_rename(move |name| {
if name.len() > 2
&& name.starts_with("SP")
&& name.chars().nth(2).unwrap().is_uppercase()
if name == "SPCompressionCode"
{
name[2..].to_string()
"CompressionCode".to_string()
} else {
name
}
})
.generate_csharp_file(format!("ServicePoint/BindGen/{}.g.cs", &class))
.generate_csharp_file(format!("ServicePoint/{class}.g.cs"))
.unwrap();
}
}

View file

@ -1,20 +1,24 @@
using ServicePoint;
using CompressionCode = ServicePoint.BindGen.CompressionCode;
using var connection = Connection.Open("127.0.0.1:2342");
if (connection == null)
{
Console.Error.WriteLine("could not connect");
return;
}
connection.Send(Command.Clear().IntoPacket());
connection.Send(Command.Brightness(128).IntoPacket());
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
using var pixels = new Bitmap(Constants.PixelWidth, Constants.PixelHeight);
for (nuint offset = 0; offset < nuint.MaxValue; offset++)
{
pixels.Fill(false);
for (nuint y = 0; y < pixels.Height; y++)
for (nuint y = 0; y < pixels.Height(); y++)
pixels[(y + offset) % Constants.PixelWidth, y] = true;
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone(), CompressionCode.Lzma).IntoPacket());
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone(), CompressionCode.Lzma));
Thread.Sleep(14);
}

@ -0,0 +1 @@
Subproject commit 2dcf44a5c398925249cf96e9bbf724dd551e5b76