Forum

Enttec OpenDMX - C# (VS)/VL discrepancy when using native library

I’m not entirely sure this is a bug but it’s definitely strange behavior.

I’m trying to make native nodes for the Enttec OpenDMX (and other compatible) devices.

My starting point is the example code Enttec provides on their website
https://dol2kh495zr52.cloudfront.net/download/examples/OpenDMX.cs
https://dol2kh495zr52.cloudfront.net/download/examples/Csharp_example.zip

The examples have no issues detecting and connecting to the device. I made a little library to wrap the OpenDMX object and also the following super simple test code:

static void Main(string[] args)
    {
        var openDmx = new OpenDMX();
        openDmx.start();
        openDmx.setDmxValue(1, 255);
        Console.ReadLine();
    }

Ran from VS this connects to the device and outputs full value on channel 1 for a brief period. Works fine.

I made equivalent code in VL

image

and also tried using the script region

Both VL methods output this:

image

The process is that

  1. start() connects to the device using FT_Open() which receives the device handle (this should stay valid for the duration of the session)
  2. this in turn starts the initialization that uses the handle to do a few init operations on the device

The handle stays valid when ran from VS but somehow when running from VL the connection still performs fine but somehow the handle is not valid for any subsequent operations (debugged with breakpoints). Any idea where this discrepancy could be coming from?

Sidenote: The original implemention has the class and its methods as static but that did exactly the same and looked like a complete mess in VL (floating nodes with no inputs).

Here’s the library/documents even though I assume it might be slightly tedious to test without the device itself

OpenDMXNetFramework.zip (54.7 KB)

OpenDMXWrapper3.vl (8.4 KB)

For this document to load properly the previous document needs to be loaded before. VL doesn’t reference stuff when only used in a Script region?
OpenDMXWrapperScript.vl (4.0 KB)

this concept is not really correct, since all methods are static. usually such (non-static) wrappers get and encapsulate the handle by acquiring one on create and implement IDisposable to correctly release the handle. so you have an instance that calls the native static methods on the handle, but looks like a non-static class from the outside.

like this you try to create a new handle each time you call start(), which might be invalid since usually a process can do this only once per life time. to do it a second time, the first handle needs to be released or the vvvv process needs to be restarted.

similar to this, but create the hand in the constructor:

The native dll imported methods are static yeah, but the handle is being kept with the object and I’m calling the start only once. I put it into the constructor and implemented a Dispose that closes the handle but it’s not really helping and I’m not surprised either. As I said I already had it fully static before, it just looked like a mess.

And even if the process isn’t 100% correct now as I’m just trying to get the absolute basics to work I fail to see the difference between the code in VL and C#. And still in C# it’s working absolutely fine while in VL the handle becomes unusable right away :(

image

public static OpenDMX ConnectDMX()
    {
        uint handle = 0;
        var status = FT_Open(0, ref handle);

        Console.WriteLine("Opening connection");
        Console.WriteLine(handle);
        Console.WriteLine(status);

        return new OpenDMX(handle);
    }

    public OpenDMX(uint _handle)
    {
        handle = _handle;
    }

Seems like it’s a 64 vs 32bit related issue, tested in 32bit alpha and the behavior seems better, the handle keeps being valid even though output still doesn’t work but I’ll probably figure that out. I’ll try to see if there’s a 64bit version of the library, I thought it just wouldn’t load otherwise but it did. If the handle refers to a memory location then it does make sense.

a classic…

Yeah, sorry for bothering you with this.

Oddly enough using the x86 FTD2XX.dll works across platforms as long as the handles are not typed as uint but as System.UIntPtr.

Also more readable when using an alias.

using FT_HANDLE = System.UIntPtr;

With the functions declared as follows

[DllImport("FTD2XX.dll")]
    public static extern FT_STATUS FT_Open(UInt32 uiPort, ref FT_HANDLE ftHandle);

On another note, is there some workflow of unlocking and reloading a referenced DLL so it can be rebuilt and updated without reloading vvvv?

does System.IntPtr also work? which would be the more common way to type it.

this is not possible in the .NET framework runtime, but the .NET Core runtime might make this possible in the future.