Skip to content

Commit

Permalink
Merge remote-tracking branch 'kyle/better-csharp-bindings'
Browse files Browse the repository at this point in the history
  • Loading branch information
malloch committed Jun 20, 2024
2 parents d01e871 + 14dea06 commit b46a29e
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 103 deletions.
26 changes: 13 additions & 13 deletions bindings/csharp/Mapper.NET/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ public Device(string name)
}

public Device(string name, Graph graph)
: base(mpr_dev_new(name, graph._obj))
: base(mpr_dev_new(name, graph.NativePtr))
{
_owned = true;
}

// construct from mpr_dev pointer
internal Device(IntPtr dev) : base(dev)
public Device(IntPtr dev) : base(dev)
{
}

/// <summary>
/// If the device is ready to send and receive signals.
/// </summary>
public bool Ready => mpr_dev_get_is_ready(_obj) != 0;
public bool Ready => mpr_dev_get_is_ready(NativePtr) != 0;

/// <summary>
/// Return the list of all maps for this device. Use <see cref="GetMaps" /> if you want to filter by direction.
Expand All @@ -40,8 +40,8 @@ internal Device(IntPtr dev) : base(dev)
/// </summary>
public Time Time
{
get => new(mpr_dev_get_time(_obj));
set => mpr_dev_set_time(_obj, value.data.ntp);
get => new(mpr_dev_get_time(NativePtr));
set => mpr_dev_set_time(NativePtr, value.data.ntp);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
Expand All @@ -66,7 +66,7 @@ public Time Time
}
}

mpr_dev_free(_obj);
mpr_dev_free(NativePtr);
}

}
Expand All @@ -92,15 +92,15 @@ public override string ToString()
/// <returns></returns>
public int Poll(int blockMs = 0)
{
return mpr_dev_poll(_obj, blockMs);
return mpr_dev_poll(NativePtr, blockMs);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern int mpr_dev_update_maps(IntPtr dev);

public Device UpdateMaps()
{
mpr_dev_update_maps(_obj);
mpr_dev_update_maps(NativePtr);
return this;
}

Expand All @@ -122,7 +122,7 @@ public Device UpdateMaps()
instPtr = new IntPtr(&numInstances);
}

var sigptr = mpr_sig_new(_obj, (int)direction, name, length, (int)mapperType, unit,
var sigptr = mpr_sig_new(NativePtr, (int)direction, name, length, (int)mapperType, unit,
IntPtr.Zero, IntPtr.Zero, instPtr, IntPtr.Zero, 0);
return new Signal(sigptr);
}
Expand All @@ -132,8 +132,8 @@ public Device UpdateMaps()

public Device RemoveSignal(Signal signal)
{
mpr_sig_free(signal._obj);
signal._obj = IntPtr.Zero;
mpr_sig_free(signal.NativePtr);
signal.NativePtr = IntPtr.Zero;
return this;
}

Expand All @@ -160,7 +160,7 @@ public new Device Push()

public MapperList<Signal> GetSignals(Signal.Direction direction = Signal.Direction.Any)
{
return new MapperList<Signal>(mpr_dev_get_sigs(_obj, (int)direction), MapperType.Signal);
return new MapperList<Signal>(mpr_dev_get_sigs(NativePtr, (int)direction), MapperType.Signal);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
Expand All @@ -173,7 +173,7 @@ public MapperList<Signal> GetSignals(Signal.Direction direction = Signal.Directi
/// <returns></returns>
public MapperList<Map> GetMaps(Signal.Direction direction)
{
return new MapperList<Map>(mpr_dev_get_maps(_obj, (int)direction), MapperType.Map);
return new MapperList<Map>(mpr_dev_get_maps(NativePtr, (int)direction), MapperType.Map);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
Expand Down
114 changes: 86 additions & 28 deletions bindings/csharp/Mapper.NET/Graph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,54 @@

namespace Mapper;

/// <summary>
/// Graphs are the primary interface through which a program may observe the distributed
/// graph and store information about devices and signals that are present.
/// Each Graph stores records of devices, signals, and maps, which can be queried.
/// </summary>
public class Graph : MapperObject
{
/// <summary>
/// Events fired by Graphs
/// </summary>
public enum Event
{
New, //!< New record has been added to the graph.
Modified, //!< The existing record has been modified.
Removed, //!< The existing record has been removed.
Expired //!< The graph has lost contact with the remote entity.
/// <summary>
/// New record has been added to the graph
/// </summary>
New,
/// <summary>
/// An existing record has been modified
/// </summary>
Modified,
/// <summary>
/// An existing record has been removed
/// </summary>
Removed,
/// <summary>
/// The graph has lost contact with the remote object
/// </summary>
Expired
}

private readonly List<Handler> handlers = new();

internal Graph(IntPtr obj) : base(obj)
internal Graph(IntPtr nativePtr) : base(nativePtr)
{
}

public Graph(MapperType flags) : base(mpr_graph_new((int)flags))
/// <summary>
/// Create a new graph, specifying the types of objects to automatically subscribe to.
/// </summary>
/// <param name="autosubscribe_types">A combination of <see cref="MapperType" /> values indicating what this graph should automatically subscribe to</param>
public Graph(MapperType autosubscribe_types) : base(mpr_graph_new((int)autosubscribe_types))
{
_owned = true;
}

/// <summary>
/// Create a new graph that will automatically subscribe to all object types.
/// </summary>
public Graph() : base(mpr_graph_new((int)MapperType.Object))
{
_owned = true;
Expand All @@ -37,7 +64,7 @@ public Graph() : base(mpr_graph_new((int)MapperType.Object))

~Graph()
{
if (_owned) mpr_graph_free(_obj);
if (_owned) mpr_graph_free(NativePtr);
}

public new Graph SetProperty<TProperty, TValue>(TProperty property, TValue value, bool publish)
Expand All @@ -64,68 +91,99 @@ public Graph() : base(mpr_graph_new((int)MapperType.Object))
/// </summary>
public string? Interface
{
get => Marshal.PtrToStringAnsi(mpr_graph_get_interface(_obj));
get => Marshal.PtrToStringAnsi(mpr_graph_get_interface(NativePtr));
set
{
if (value == null)
{
throw new ArgumentException("Cannot set interface to null.");
}
mpr_graph_set_interface(_obj, value);
mpr_graph_set_interface(NativePtr, value);
}
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern void mpr_graph_set_address(IntPtr graph,
private static extern int mpr_graph_set_address(IntPtr graph,
[MarshalAs(UnmanagedType.LPStr)] string group,
int port);

public Graph SetAddress(string group, int port)
/// <summary>
/// Set the multicast group and port to use
/// </summary>
/// <param name="group">Multicast group</param>
/// <param name="port">Port to use for communication</param>
/// <returns>True if successful, false otherwise</returns>
public bool SetAddress(string group, int port)
{
mpr_graph_set_address(_obj, group, port);
return this;
return mpr_graph_set_address(NativePtr, group, port) == 0;
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr mpr_graph_get_address(IntPtr graph);

public string? Address => Marshal.PtrToStringAnsi(mpr_graph_get_address(_obj));
/// <summary>
/// A string specifying the multicast URL for bus communication with the distributed graph.
/// </summary>
public string? Address => Marshal.PtrToStringAnsi(mpr_graph_get_address(NativePtr));

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern int mpr_graph_poll(IntPtr graph, int block_ms);

/// <summary>
/// Synchronize a local graph copy with the distributed graph.
/// </summary>
/// <param name="block_ms">Optionally block for this many milliseconds while polling. A value of 0 will not block.</param>
/// <returns>Number of handled messages</returns>
public int Poll(int block_ms = 0)
{
return mpr_graph_poll(_obj, block_ms);
return mpr_graph_poll(NativePtr, block_ms);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern void mpr_graph_subscribe(IntPtr graph, IntPtr dev, int types, int timeout);

public Graph Subscribe(Device device, MapperType mapperTypes, int timeout = -1)
/// <summary>
/// Subscribe to receive events for a specific device
/// </summary>
/// <param name="device">Device to receive events from</param>
/// <param name="mapperTypes">Types of information to raise events for</param>
/// <param name="timeout">Length of time in seconds to subscribe for. -1 is indefinite.</param>
public void Subscribe(Device device, MapperType mapperTypes, int timeout = -1)
{
mpr_graph_subscribe(_obj, device._obj, (int)mapperTypes, timeout);
return this;
mpr_graph_subscribe(NativePtr, device.NativePtr, (int)mapperTypes, timeout);
}

public Graph Subscribe(MapperType mapperTypes, int timeout = -1)
/// <summary>
/// Subscribe to receive events for the entire graph
/// </summary>
/// <param name="mapperTypes">Types of information to raise events for</param>
/// <param name="timeout">Length of time in seconds to subscribe for. -1 is indefinite.</param>
public void Subscribe(MapperType mapperTypes, int timeout = -1)
{
mpr_graph_subscribe(_obj, IntPtr.Zero, (int)mapperTypes, timeout);
return this;
mpr_graph_subscribe(NativePtr, IntPtr.Zero, (int)mapperTypes, timeout);
}

[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern void mpr_graph_unsubscribe(IntPtr graph, IntPtr dev);

/// <summary>
/// Unsubscribe from events for a specific device
/// </summary>
/// <param name="device"></param>
/// <returns></returns>
public Graph Unsubscribe(Device device)
{
mpr_graph_unsubscribe(_obj, device._obj);
mpr_graph_unsubscribe(NativePtr, device.NativePtr);
return this;
}

/// <summary>
/// Unsubscribe from events for the entire graph
/// </summary>
/// <returns></returns>
public Graph Unsubscribe()
{
mpr_graph_unsubscribe(_obj, IntPtr.Zero);
mpr_graph_unsubscribe(NativePtr, IntPtr.Zero);
return this;
}

Expand Down Expand Up @@ -164,7 +222,7 @@ public Graph AddCallback(Action<object, Event> callback, MapperType mapperTypes
{
// TODO: check if handler is already registered
if (handlers.Count == 0)
mpr_graph_add_cb(_obj,
mpr_graph_add_cb(NativePtr,
Marshal.GetFunctionPointerForDelegate(new HandlerDelegate(_handler)),
(int)MapperType.Object,
IntPtr.Zero);
Expand All @@ -188,7 +246,7 @@ public Graph RemoveCallback(Action<object, Event> callback)
{
handlers.RemoveAt(found);
if (handlers.Count == 0)
mpr_graph_remove_cb(_obj,
mpr_graph_remove_cb(NativePtr,
Marshal.GetFunctionPointerForDelegate(new HandlerDelegate(_handler)),
IntPtr.Zero);
}
Expand All @@ -199,9 +257,9 @@ public Graph RemoveCallback(Action<object, Event> callback)
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr mpr_graph_get_list(IntPtr graph, int type);

public MapperList<Device> Devices => new(mpr_graph_get_list(_obj, (int)MapperType.Device), MapperType.Device);
public MapperList<Signal> Signals => new(mpr_graph_get_list(_obj, (int)MapperType.Signal), MapperType.Signal);
public MapperList<Map> Maps => new(mpr_graph_get_list(_obj, (int)MapperType.Map), MapperType.Map);
public MapperList<Device> Devices => new(mpr_graph_get_list(NativePtr, (int)MapperType.Device), MapperType.Device);
public MapperList<Signal> Signals => new(mpr_graph_get_list(NativePtr, (int)MapperType.Signal), MapperType.Signal);
public MapperList<Map> Maps => new(mpr_graph_get_list(NativePtr, (int)MapperType.Map), MapperType.Map);

private delegate void HandlerDelegate(IntPtr graph, IntPtr obj, int evt, IntPtr data);

Expand Down
Loading

0 comments on commit b46a29e

Please sign in to comment.