Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ntcore/LogMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static LogMessage ConvertToManaged(in NativeLogMessage unmanaged)
{
LogLevel = (int)unmanaged.level,
Message = unmanaged.message.ConvertToString(),
Filename = unmanaged.message.ConvertToString(),
Filename = unmanaged.filename.ConvertToString(),
Line = (int)unmanaged.line
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/ntcore/Natives/NtCore.Datalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static unsafe partial class NtCore
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial NtConnectionDataLogger StartConnectionDataLog(NtInst inst, OpaqueDataLog* log, WpiString name);

[LibraryImport("ntcore", EntryPoint = "NT_StopEntryDataLog")]
[LibraryImport("ntcore", EntryPoint = "NT_StopConnectionDataLog")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void StopConnectionDataLog(NtConnectionDataLogger logger);
}
32 changes: 32 additions & 0 deletions src/ntcore/Natives/NtCore.Free.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ public static unsafe partial class NtCore
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void FreeCharArray(byte* nativePtr);

[LibraryImport("ntcore", EntryPoint = "NT_AllocateBooleanArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial int* AllocateBooleanArray(nuint len);

[LibraryImport("ntcore", EntryPoint = "NT_AllocateIntegerArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial long* AllocateIntegerArray(nuint len);

[LibraryImport("ntcore", EntryPoint = "NT_AllocateFloatArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial float* AllocateFloatArray(nuint len);

[LibraryImport("ntcore", EntryPoint = "NT_AllocateDoubleArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial double* AllocateDoubleArray(nuint len);

[LibraryImport("ntcore", EntryPoint = "NT_FreeBooleanArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void FreeBooleanArray(int* nativePtr);

[LibraryImport("ntcore", EntryPoint = "NT_FreeIntegerArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void FreeIntegerArray(long* nativePtr);

[LibraryImport("ntcore", EntryPoint = "NT_FreeFloatArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void FreeFloatArray(float* nativePtr);

[LibraryImport("ntcore", EntryPoint = "NT_FreeDoubleArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void FreeDoubleArray(double* nativePtr);

[LibraryImport("ntcore", EntryPoint = "NT_Meta_FreeTopicPublishers")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void MetaFreeTopicPublishers(void* nativePtr, nuint count);
Expand Down
10 changes: 10 additions & 0 deletions src/ntcore/Natives/NtCore.Listener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ public static NetworkTableEvent[] ReadListenerQueue(NtListenerPoller poller)
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void DestroyListenerPoller(NtListenerPoller poller);


[LibraryImport("ntcore", EntryPoint = "NT_WaitForListenerQueue")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[return: MarshalAs(UnmanagedType.I4)]
public static partial bool WaitForListenerQueue(int handle, double timeout);

[LibraryImport("ntcore", EntryPoint = "NT_AddPolledListenerSingle")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial NtListener AddListener(NtListenerPoller poller, WPIUtil.WpiString prefix, EventFlags flags);

[LibraryImport("ntcore", EntryPoint = "NT_AddPolledListenerMultiple")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static partial NtListener AddListener(NtListenerPoller poller, [MarshalUsing(typeof(WpiStringMarshaller), ElementIndirectionDepth = 1)] ReadOnlySpan<string> prefixes, nuint prefixesLen, EventFlags flags);
Expand Down
7 changes: 4 additions & 3 deletions src/ntcore/NetworkMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ namespace NetworkTables;
[Flags]
public enum NetworkMode : uint
{
None = 0,
None = 0x0,
Server = 0x1,
Client3 = 0x2,
Client4 = 0x4,
Client = 0x4,
Client4 = Client,
Starting = 0x8,
Local = 0x10,
MdnsAnnouncing = 0x20,
}
39 changes: 13 additions & 26 deletions src/ntcore/PubSubOptions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using NetworkTables.Handles;

namespace NetworkTables;

[NativeMarshalling(typeof(PubSubOptionsMarshaller))]
[StructLayout(LayoutKind.Auto)]
public record struct PubSubOptions(uint PollSize, double Periodic, bool ExcludePublisher, bool SendAll, bool TopicsOnly, bool PrefixMatch, bool KeepDuplicates, bool DisableRemote, bool DisableLocal, bool ExcludeSelf, bool Hidden)
public record struct PubSubOptions(uint PollStorage, double Periodic, NtPublisher ExcludePublisher, bool SendAll, bool TopicsOnly, bool PrefixMatch, bool KeepDuplicates, bool DisableRemote, bool DisableLocal, bool ExcludeSelf, bool Hidden)
{
public static PubSubOptions None => new();

public uint PollSize
{
get => PollStorage;
set => PollStorage = value;
}
}

[CustomMarshaller(typeof(PubSubOptions), MarshalMode.Default, typeof(PubSubOptionsMarshaller))]
Expand All @@ -18,9 +25,9 @@ public static NativePubSubOptions ConvertToUnmanaged(in PubSubOptions managed)
return new NativePubSubOptions
{
structSize = (uint)sizeof(NativePubSubOptions),
pollSize = managed.PollSize,
pollStorage = managed.PollStorage,
periodic = managed.Periodic,
excludePublisher = managed.ExcludePublisher ? 1 : 0,
excludePublisher = managed.ExcludePublisher.Handle,
sendAll = managed.SendAll ? 1 : 0,
topicsOnly = managed.TopicsOnly ? 1 : 0,
prefixMatch = managed.PrefixMatch ? 1 : 0,
Expand All @@ -36,9 +43,9 @@ public static PubSubOptions ConvertToManaged(in NativePubSubOptions unmanaged)
{
return new PubSubOptions
{
PollSize = unmanaged.pollSize,
PollStorage = unmanaged.pollStorage,
Periodic = unmanaged.periodic,
ExcludePublisher = unmanaged.excludePublisher != 0,
ExcludePublisher = new NtPublisher(unmanaged.excludePublisher),
SendAll = unmanaged.sendAll != 0,
TopicsOnly = unmanaged.topicsOnly != 0,
PrefixMatch = unmanaged.prefixMatch != 0,
Expand All @@ -54,7 +61,7 @@ public static PubSubOptions ConvertToManaged(in NativePubSubOptions unmanaged)
public struct NativePubSubOptions
{
public uint structSize;
public uint pollSize;
public uint pollStorage;
public double periodic;
public int excludePublisher;
public int sendAll;
Expand All @@ -65,25 +72,5 @@ public struct NativePubSubOptions
public int disableLocal;
public int excludeSelf;
public int hidden;

public override bool Equals(object? obj)
{
throw new NotImplementedException();
}

public override int GetHashCode()
{
throw new NotImplementedException();
}

public static bool operator ==(NativePubSubOptions left, NativePubSubOptions right)
{
return left.Equals(right);
}

public static bool operator !=(NativePubSubOptions left, NativePubSubOptions right)
{
return !(left == right);
}
}
}
10 changes: 9 additions & 1 deletion src/wpiutil/Natives/RawFrameNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public void FromManaged(in RawFrameWriter managed)
rawFrame.height = managed.Height;
rawFrame.stride = managed.Stride;
rawFrame.pixelFormat = managed.PixelFormat;
rawFrame.timestamp = managed.Timestamp;
rawFrame.timestampSrc = managed.TimestampSource;
}
public readonly ref readonly byte GetPinnableReference()
{
Expand All @@ -49,13 +51,17 @@ public unsafe partial struct NativeRawFrame
{
[LibraryImport("wpiutil", EntryPoint = "WPI_AllocateRawFrameData")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[return: MarshalAs(UnmanagedType.U4)]
[return: MarshalAs(UnmanagedType.I4)]
public static unsafe partial bool AllocateRawFrameData(ref NativeRawFrame frame, nuint requestedSize);

[LibraryImport("wpiutil", EntryPoint = "WPI_FreeRawFrameData")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void FreeRawFrameData(ref NativeRawFrame frame);

[LibraryImport("wpiutil", EntryPoint = "WPI_SetRawFrameData")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void SetRawFrameData(ref NativeRawFrame frame, void* data, nuint size, nuint capacity, void* cbdata, delegate* unmanaged[Cdecl]<void*, void*, nuint, void> freeFunc);

public byte* data;
public delegate* unmanaged[Cdecl]<void*, void*, nuint, void> freeFunc;
public void* freeCbData;
Expand All @@ -65,4 +71,6 @@ public unsafe partial struct NativeRawFrame
public int width;
public int height;
public int stride;
public ulong timestamp;
public TimestampSource timestampSrc;
}
16 changes: 16 additions & 0 deletions src/wpiutil/Natives/StringsNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ namespace WPIUtil.Natives;

public static partial class StringsNative
{
[LibraryImport("wpiutil", EntryPoint = "WPI_InitString")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void InitString(WpiStringMarshaller.WpiStringNative* wpiString);

[LibraryImport("wpiutil", EntryPoint = "WPI_InitStringWithLength")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void InitStringWithLength(WpiStringMarshaller.WpiStringNative* wpiString, nuint len);

[LibraryImport("wpiutil", EntryPoint = "WPI_AllocateString")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void AllocateString(WpiStringMarshaller.WpiStringNative* wpiString, nuint len);

[LibraryImport("wpiutil", EntryPoint = "WPI_AllocateStringArray")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial WpiStringMarshaller.WpiStringNative* AllocateStringArray(nuint count);

[LibraryImport("wpiutil", EntryPoint = "WPI_FreeString")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial void FreeString(WpiStringMarshaller.WpiStringNative* wpiString);
Expand Down
12 changes: 6 additions & 6 deletions src/wpiutil/Natives/SynchronizationNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace WPIUtil.Natives;

public static partial class SynchronizationNative
{
[LibraryImport("wpiutil", EntryPoint = "WPI_CreateEvent")]
[LibraryImport("wpiutil", EntryPoint = "WPI_MakeEvent")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use exported WPI_CreateEvent entry point

When code calls SynchronizationNative.CreateEvent, this import now asks the loader for WPI_MakeEvent, but the wpiutil C API still exports the C entry point as WPI_CreateEvent (the MakeEvent name is only the C++ wrapper name). This will throw EntryPointNotFoundException at runtime for any path that creates an event, so the entry point should remain WPI_CreateEvent.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using out of date information here. The entry point has changed in wpilib.

[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial WpiEventHandle CreateEvent([MarshalAs(UnmanagedType.I4)] bool manualReset, [MarshalAs(UnmanagedType.I4)] bool initialState);

Expand All @@ -23,7 +23,7 @@ public static partial class SynchronizationNative
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void ResetEvent(WpiEventHandle handle);

[LibraryImport("wpiutil", EntryPoint = "WPI_CreateSemaphore")]
[LibraryImport("wpiutil", EntryPoint = "WPI_MakeSemaphore")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use exported WPI_CreateSemaphore entry point

When code calls SynchronizationNative.CreateSemaphore, this import now looks for WPI_MakeSemaphore, but the native C ABI exports WPI_CreateSemaphore (the MakeSemaphore spelling is the C++ wrapper). Any semaphore creation will fail at runtime with EntryPointNotFoundException, so keep this P/Invoke bound to WPI_CreateSemaphore.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you're using out of date information here.

[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial WpiSemaphoreHandle CreateSemaphore(int initialCount, int maximumCount);

Expand All @@ -33,17 +33,17 @@ public static partial class SynchronizationNative

[LibraryImport("wpiutil", EntryPoint = "WPI_ReleaseSemaphore")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[return: MarshalAs(UnmanagedType.U4)]
[return: MarshalAs(UnmanagedType.I4)]
public static unsafe partial bool ReleaseSemaphore(WpiSemaphoreHandle handle, int releaseCount, out int prevCount);

[LibraryImport("wpiutil", EntryPoint = "WPI_WaitForObject")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[return: MarshalAs(UnmanagedType.U4)]
[return: MarshalAs(UnmanagedType.I4)]
public static partial bool WaitForObject(int handle);

[LibraryImport("wpiutil", EntryPoint = "WPI_WaitForObjectTimeout")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[return: MarshalAs(UnmanagedType.U4)]
[return: MarshalAs(UnmanagedType.I4)]
public static unsafe partial bool WaitForObjectTimeout(int handle, double timeout, [MarshalAs(UnmanagedType.I4)] out bool timedOut);

[LibraryImport("wpiutil", EntryPoint = "WPI_WaitForObjects")]
Expand All @@ -64,7 +64,7 @@ public static unsafe ReadOnlySpan<int> WaitForObjects(ReadOnlySpan<int> handles,
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe partial int WaitForObjectsTimeout(ReadOnlySpan<int> handles, int handlesCount, Span<int> signaled, double timeout, [MarshalAs(UnmanagedType.I4)] out bool timedOut);

[LibraryImport("wpiutil", EntryPoint = "WPI_CreateSemaphore")]
[LibraryImport("wpiutil", EntryPoint = "WPI_CreateSignalObject")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial void CreateSignalObject(int handle, [MarshalAs(UnmanagedType.I4)] bool manualReset, [MarshalAs(UnmanagedType.I4)] bool InitialState);

Expand Down
11 changes: 10 additions & 1 deletion src/wpiutil/PixelFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,14 @@ public enum PixelFormat : int
Bgr,
Gray,
Y16,
Uyvy
Uyvy,
Bgra
}

public enum TimestampSource : int
{
Unknown = 0,
FrameDequeue,
V4lEof,
V4lSoe
}
16 changes: 16 additions & 0 deletions src/wpiutil/RawFrameReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,24 @@ public PixelFormat PixelFormat
set => internalFrame.pixelFormat = value;
}

public ulong Timestamp
{
get => internalFrame.timestamp;
set => internalFrame.timestamp = value;
}

public TimestampSource TimestampSource
{
get => internalFrame.timestampSrc;
set => internalFrame.timestampSrc = value;
}

public unsafe RawFrameReader CreateCopy()
{
RawFrameReader ret = new RawFrameReader();
ret.SetInfo(Width, Height, Stride, PixelFormat);
ret.Timestamp = Timestamp;
ret.TimestampSource = TimestampSource;
NativeRawFrame.AllocateRawFrameData(ref ret.RawFrame, internalFrame.size);
ret.internalFrame.size = internalFrame.size;
new ReadOnlySpan<byte>(internalFrame.data, checked((int)internalFrame.size)).CopyTo(new Span<byte>(ret.internalFrame.data, (int)ret.internalFrame.size));
Expand All @@ -68,6 +82,8 @@ public unsafe RawFrameWriter ToWriter()
Height = Height,
Stride = Stride,
PixelFormat = PixelFormat,
Timestamp = Timestamp,
TimestampSource = TimestampSource,
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/wpiutil/RawFrameWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public readonly ref struct RawFrameWriter
public int Height { get; init; }
public int Stride { get; init; }
public PixelFormat PixelFormat { get; init; }
public ulong Timestamp { get; init; }
public TimestampSource TimestampSource { get; init; }
}
Loading