diff --git a/api/clroni/clroni-repl/Repl.cs b/api/clroni/clroni-repl/Repl.cs index 818b03c..14386da 100644 --- a/api/clroni/clroni-repl/Repl.cs +++ b/api/clroni/clroni-repl/Repl.cs @@ -1,29 +1,19 @@ using oni; -using System; using System.Runtime.InteropServices; -using System.Threading; using CommandLine; -using System.Linq; using CommandLine.Text; namespace ClrOniRepl { - class DataProcessor + class DataProcessor(Context context, bool display = false, ulong displayEvery = 1000) { - private readonly Context context; + private readonly Context context = context; public volatile bool Quit = false; - public bool Display { get; set; } + public bool Display { get; set; } = display; - public ulong DisplayEvery { get; set; } - - public DataProcessor(Context context, bool display = false, ulong displayEvery = 1000) - { - this.context = context; - Display = display; - DisplayEvery = displayEvery; - } + public ulong DisplayEvery { get; set; } = displayEvery; public void CaptureData() { @@ -219,7 +209,12 @@ static void Main(string[] args) break; case 'x': + processor.Quit = true; + procThread.Join(200); ctx.Refresh(); + Console.Write(Helpers.DeviceTableString(ctx)); + ctx.Start(true); + procThread.Start(); break; default: diff --git a/api/clroni/clroni-repl/clroni-repl.csproj b/api/clroni/clroni-repl/clroni-repl.csproj index b96bbb1..68cf03b 100644 --- a/api/clroni/clroni-repl/clroni-repl.csproj +++ b/api/clroni/clroni-repl/clroni-repl.csproj @@ -1,10 +1,11 @@ - + - ONI RELLPL (RCRLLR)(CLR) + ONI REPL Test application for clroni. ONI Open Ephys - net472 + net8.0 + enable 1.2.2 MIT Copyright © Open Ephys, Inc. diff --git a/api/clroni/clroni/Context.cs b/api/clroni/clroni/Context.cs index fdccd23..89a1f56 100644 --- a/api/clroni/clroni/Context.cs +++ b/api/clroni/clroni/Context.cs @@ -5,6 +5,7 @@ using System.Security.Permissions; using System.Text; + namespace oni { /// @@ -183,17 +184,24 @@ private int GetIntOption(int option, bool drv_opt = false) // String GetOption private string GetStringOption(int option, bool drv_opt = false) { + const int BufferSize = 1000; + var sz = Marshal.AllocHGlobal(IntPtr.Size); if (IntPtr.Size == 4) { - Marshal.WriteInt32(sz, 1000); + Marshal.WriteInt32(sz, BufferSize); } else { - Marshal.WriteInt64(sz, 1000); + Marshal.WriteInt64(sz, BufferSize); } - var str = new StringBuilder(1000); + +#if NET7_0_OR_GREATER + var str = new char[BufferSize]; +#else + var str = new StringBuilder(BufferSize); +#endif int rc; if (!drv_opt) @@ -555,8 +563,12 @@ public void Dispose() /// by IDisposable. /// /// +#if NET7_0_OR_GREATER + protected virtual void Dispose(bool disposing) +#else [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] protected virtual void Dispose(bool disposing) +#endif { if (ctx != null && !ctx.IsInvalid) diff --git a/api/clroni/clroni/ContextHandle.cs b/api/clroni/clroni/ContextHandle.cs index 91978aa..49a16d5 100644 --- a/api/clroni/clroni/ContextHandle.cs +++ b/api/clroni/clroni/ContextHandle.cs @@ -2,15 +2,19 @@ using System.Runtime.ConstrainedExecution; using System.Security.Permissions; + namespace oni { +#if NET7_0_OR_GREATER + internal class ContextHandle : SafeHandleZeroOrMinusOneIsInvalid +#else [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] internal unsafe class ContextHandle : SafeHandleZeroOrMinusOneIsInvalid +#endif { - internal ContextHandle() : base(true) { } + public ContextHandle() : base(true) { } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected override bool ReleaseHandle() { return NativeMethods.oni_destroy_ctx(handle) == 0; diff --git a/api/clroni/clroni/Frame.cs b/api/clroni/clroni/Frame.cs index a493504..d83c5f3 100644 --- a/api/clroni/clroni/Frame.cs +++ b/api/clroni/clroni/Frame.cs @@ -1,18 +1,23 @@ using Microsoft.Win32.SafeHandles; using System; -using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; +using System.Runtime.ConstrainedExecution; using System.Security.Permissions; + namespace oni { /// /// Managed wrapper for an ONI-compliant data frame implementation. Produced by calls /// to . /// +#if NET7_0_OR_GREATER + public unsafe class Frame : SafeHandleZeroOrMinusOneIsInvalid +#else [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] public unsafe class Frame : SafeHandleZeroOrMinusOneIsInvalid +#endif { [StructLayout(LayoutKind.Sequential)] @@ -36,8 +41,12 @@ internal Frame(IntPtr handle) /// /// True if the handle is released successfully (always the case /// in this implementation) +#if NET7_0_OR_GREATER + protected override bool ReleaseHandle() +#else [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] protected override bool ReleaseHandle() +#endif { GC.RemoveMemoryPressure(((frame_t*)handle.ToPointer())->data_sz); NativeMethods.oni_destroy_frame(handle); diff --git a/api/clroni/clroni/NativeMethods.Common.cs b/api/clroni/clroni/NativeMethods.Common.cs new file mode 100644 index 0000000..c18b31b --- /dev/null +++ b/api/clroni/clroni/NativeMethods.Common.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace oni +{ + /// + /// Common language runtime bindings to liboni C library. The functionality + /// these bindings is exposed through higher-order types: , + /// , , , + /// and . + /// + [SuppressUnmanagedCodeSecurity] // NB: Call into native code without incurring the performance loss of a run-time security check when doing so + public static partial class NativeMethods + { + /// + /// Semantic version of this library. + /// + public static readonly Version LibraryVersion; + + const string LibraryName = "liboni"; + + static NativeMethods() + { + // Set once LibraryVersion to version() + oni_version(out int major, out int minor, out int patch); + LibraryVersion = new Version(major, minor, patch); + + // Make sure it is supported + if (major < 4) + { + throw VersionNotSupported(null, ">= v4.0.0"); + } + } + + private static NotSupportedException VersionNotSupported(string methodName, string requiredVersion) + { + return new NotSupportedException( + string.Format( + "{0}liboni version not supported. Required version {1}", + methodName == null ? string.Empty : methodName + ": ", + requiredVersion)); + } + } +} diff --git a/api/clroni/clroni/oni.cs b/api/clroni/clroni/NativeMethods.Framework.cs similarity index 71% rename from api/clroni/clroni/oni.cs rename to api/clroni/clroni/NativeMethods.Framework.cs index fabfec4..f567432 100644 --- a/api/clroni/clroni/oni.cs +++ b/api/clroni/clroni/NativeMethods.Framework.cs @@ -1,56 +1,18 @@ +using oni; using System; +using System.Collections.Generic; +using System.Linq; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -using System.Security; using System.Text; namespace oni { - /// - /// Common language runtime bindings to liboni C library. The functionality - /// these bindings is exposed through higher-order types: , - /// , , , - /// and . - /// - [SuppressUnmanagedCodeSecurity] // NB: Call into native code without incurring the performance loss of a run-time security check when doing so public static partial class NativeMethods { - /// - /// Semantic version of this library. - /// - public static readonly Version LibraryVersion; - private const CallingConvention CCCdecl = CallingConvention.Cdecl; - private const string LibraryName = "liboni"; - - // The static constructor prepares static readonly fields - static NativeMethods() - { - // Set once LibraryVersion to version() - oni_version(out int major, out int minor, out int patch); - LibraryVersion = new Version(major, minor, patch); - - // Make sure it is supported - if (major < 4) - { - throw VersionNotSupported(null, ">= v4.0.0"); - } - } - - private static NotSupportedException VersionNotSupported(string methodName, string requiredVersion) - { - return new NotSupportedException( - string.Format( - "{0}liboni version not supported. Required version {1}", - methodName == null ? string.Empty : methodName + ": ", - requiredVersion)); - } - - - - - [DllImport(LibraryName, CallingConvention = CCCdecl)] + [DllImport(LibraryName, CallingConvention = CCCdecl, CharSet = CharSet.Ansi)] internal static extern void oni_version(out int major, out int minor, out int patch); [DllImport(LibraryName, CallingConvention = CCCdecl, CharSet = CharSet.Ansi)] diff --git a/api/clroni/clroni/NativeMethods.NET8.cs b/api/clroni/clroni/NativeMethods.NET8.cs new file mode 100644 index 0000000..f041929 --- /dev/null +++ b/api/clroni/clroni/NativeMethods.NET8.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Runtime.CompilerServices; + +namespace oni +{ + public static partial class NativeMethods + { + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial void oni_version(out int major, out int minor, out int patch); + + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static extern ContextHandle oni_create_ctx(string driver_name); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_init_ctx(ContextHandle ctx, int host_idx); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_destroy_ctx(IntPtr ctx); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_get_opt(ContextHandle ctx, int option, IntPtr val, IntPtr size); + + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static extern int oni_get_opt(ContextHandle ctx, int option, [Out] char[] val, IntPtr size); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_set_opt(ContextHandle ctx, int option, IntPtr val, int size); + + [LibraryImport(LibraryName, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_set_opt(ContextHandle ctx, int option, string val, int size); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial IntPtr oni_get_driver_info(ContextHandle ctx); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_get_driver_opt(ContextHandle ctx, int option, IntPtr val, IntPtr size); + + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] + internal static extern int oni_get_driver_opt(ContextHandle ctx, int option, [Out] char[] val, IntPtr size); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_set_driver_opt(ContextHandle ctx, int option, IntPtr val, int size); + + [LibraryImport(LibraryName, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_set_driver_opt(ContextHandle ctx, int option, string val, int size); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_read_reg(ContextHandle ctx, uint dev_idx, uint addr, IntPtr val); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_write_reg(ContextHandle ctx, uint dev_idx, uint addr, uint val); + + //[DllImport(LibraryName, CallingConvention = CCCdecl, SetLastError = true)] + //internal static extern int oni_read_frame(ContextHandle ctx, out Frame frame); + + [LibraryImport(LibraryName, SetLastError = true)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_read_frame(ContextHandle ctx, out IntPtr frame); + + //[DllImport(LibraryName, CallingConvention = CCCdecl, SetLastError = true)] + //internal static extern int oni_create_frame(ContextHandle ctx, out Frame frame, uint dev_idx, IntPtr data, uint data_sz); + + //[DllImport(LibraryName, CallingConvention = CCCdecl, SetLastError = true)] + //internal static extern int oni_write_frame(ContextHandle ctx, Frame frame); + + [LibraryImport(LibraryName, SetLastError = true)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_create_frame(ContextHandle ctx, out IntPtr frame, uint dev_idx, IntPtr data, uint data_sz); + + [LibraryImport(LibraryName, SetLastError = true)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial int oni_write_frame(ContextHandle ctx, IntPtr frame); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial void oni_destroy_frame(IntPtr frame); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial IntPtr oni_error_str(int err); + } +} diff --git a/api/clroni/clroni/ONIException.cs b/api/clroni/clroni/ONIException.cs index a5cd4f2..fde5fc1 100644 --- a/api/clroni/clroni/ONIException.cs +++ b/api/clroni/clroni/ONIException.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; + namespace oni { /// @@ -15,10 +16,13 @@ public class ONIException : Exception /// public readonly int Number; + /// + /// Initializes a new + /// protected ONIException() { } /// - /// Initializes a new + /// Initializes a new /// /// The error code returned by the native ONI API. internal ONIException(int errnum) @@ -32,8 +36,10 @@ internal ONIException(int errnum) public override string Message => Marshal.PtrToStringAnsi(NativeMethods.oni_error_str(Number)); +#if !NET7_0_OR_GREATER protected ONIException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/api/clroni/clroni/clroni.csproj b/api/clroni/clroni/clroni.csproj index f05bf3c..f0e40b2 100644 --- a/api/clroni/clroni/clroni.csproj +++ b/api/clroni/clroni/clroni.csproj @@ -1,16 +1,12 @@ - + CLR bindings for liboni CLR bindings to liboni, an ONI compliant API for data acquisition. ONI Open Ephys ONIX - net472 - true -<<<<<<< riffa-hardreset - 6.2.0 -======= - 6.1.3 ->>>>>>> main + net8.0;net472;netstandard2.0 + false + 6.3.0-dev4 Jon Newman Open Ephys, Inc. ©Open Ephys, Inc. @@ -44,6 +40,16 @@ + + + + + + + + + + @@ -71,7 +77,7 @@ - + diff --git a/api/clroni/clroni/clroni.targets b/api/clroni/clroni/clroni.targets index 6343f67..87492f4 100644 --- a/api/clroni/clroni/clroni.targets +++ b/api/clroni/clroni/clroni.targets @@ -10,14 +10,14 @@ - - + + true - - + + true diff --git a/api/clroni/clroni/onix.cs b/api/clroni/clroni/onix.cs index f0677cc..89ba6ec 100644 --- a/api/clroni/clroni/onix.cs +++ b/api/clroni/clroni/onix.cs @@ -106,10 +106,20 @@ public Hub GetHub(uint device_address) [SuppressUnmanagedCodeSecurity] // NB: Call into native code without incurring the performance loss of a run-time security check when doing so public static partial class NativeMethods { +#if NET7_0_OR_GREATER + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] + internal static partial IntPtr onix_device_str(int id); + + [LibraryImport(LibraryName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] + internal static partial IntPtr onix_hub_str(int id); +#else [DllImport(LibraryName, CallingConvention = CCCdecl)] internal static extern IntPtr onix_device_str(int id); [DllImport(LibraryName, CallingConvention = CCCdecl)] internal static extern IntPtr onix_hub_str(int id); +#endif } }