-
-
Save johnty/b9ad22318bda215fcff436a166bbf8f3 to your computer and use it in GitHub Desktop.
using System; | |
using System.Threading; | |
using System.Runtime.InteropServices; | |
public class HelloWorld | |
{ | |
//[DllImport("example")] | |
//public static extern int add(int a, int b); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern IntPtr mapper_version(); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern IntPtr mapper_device_new([MarshalAs(UnmanagedType.LPStr)] string devname, int port, int net); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern IntPtr mapper_device_add_output_signal(IntPtr dev, | |
[MarshalAs(UnmanagedType.LPStr)] string name, | |
int length, | |
char type, | |
int min, | |
int max); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern int mapper_device_ready(IntPtr dev); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern int mapper_device_poll(IntPtr dev, int block_ms); | |
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] | |
public static extern void mapper_signal_update_float(IntPtr sig, float val); | |
public static void Main(string[] args) | |
{ | |
//int res = add(2,5); | |
//Console.WriteLine(res.ToString()); | |
IntPtr intPtr = mapper_version(); | |
string recv_str = "mapper version = " + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(intPtr); | |
Console.WriteLine(recv_str); | |
IntPtr dev = mapper_device_new("/CSmapper", 0, 0); | |
Console.WriteLine("created dev /CSmapper"); | |
IntPtr sig = mapper_device_add_output_signal(dev, "testsig1", 1, 'f', 0, 0); | |
Console.WriteLine("created outsig testsig1"); | |
Console.Write("Waiting for device"); | |
while (mapper_device_ready(dev) == 0) { | |
mapper_device_poll(dev, 25); | |
} | |
Console.WriteLine("Device ready!"); | |
float sig_val = 0.0F; | |
while (true) | |
{ | |
mapper_signal_update_float(sig, sig_val); | |
mapper_device_poll(dev, 25); | |
sig_val += 0.1F; | |
if (sig_val > 100) | |
sig_val = 0F; | |
Thread.Sleep(100); | |
Console.Write("Sig updated to "); | |
Console.WriteLine(sig_val.ToString()); | |
} | |
} | |
} |
If anyone's interested, I found a solution/workaround.
first, declare the mapper_device_add_input_signal
as follows:
[DllImport("mapper", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr mapper_device_add_input_signal(IntPtr dev,
[MarshalAs(UnmanagedType.LPStr)] string name,
int length,
char type,
string unit,
Int32 min,
Int32 max,
Func<IntPtr, IntPtr, IntPtr, Int32, IntPtr, IntPtr> handler,
IntPtr userData
);
Then, to declare a dummy test input signal:
IntPtr sig = mapper_device_add_input_signal(dev, "testsig1", 1, 'f', "", 0, 0, updateTest, IntPtr.Zero);
where updateTest
is
private static IntPtr updateTest(IntPtr sig, IntPtr instance, IntPtr value, Int32 count, IntPtr timetag){
unsafe
{
float val = *(float*)value;
// yay, got value...
}
return IntPtr.Zero;
}
The only downside of using this is that you've got to allow for unsafe code compilation in order to dereference the IntPtr
. If someone knows how to do this safely let me know :)
perfect! that was the next step i never got around to trying to, so thanks for that! :)
in terms of safe code, the last time i looked into it would require some wrapper functions that convert between the unsafe and safe code... i didn't investigate deeply enough to reach a conclusion whether it was doable/manageable or not... for example, is it feasible to create a higher level but more limited class in managed code which may be easier to maintain (whatever libmapper API changes would still require manual changes of this limited set of functions), versus having to convert every single function into managed code. or if there are other potentially automated ways of doing it...
Hi, that's a super nice snippet, thank you!
Do you have any idea on how to extend this to accept input signals as well? I'm currently looking at the libmapper docs and it seems that you'd somehow have to incorporate the libmapper types in C# to get it to work.
Thanks again for the snippet :)