Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/14/2018 in Posts

  1. Great article, thanks! And a pretty cool way to explain things in LV terms OK, here the detailed explanation as promised: You can find a very simple example in the ZIP file attached to my first post, GZipStream.Example.vi . There's a file Hello.txt, if you run GZipStream.Example.vi you'll get the compressed file Hello.txt.gz . To decompress it, activate the other frame of the diagram disable structure and run it. The output will be Hello2.txt . There's not much to say about this example VI, the code consists of just .NET invoke nodes and properties. The code of CreateGZIPStream.vi is that what matters here. We use .NET reflection to call a constructor that would be otherwise inaccessable for LV. Reflection is the ability to query a .NET assembly (DLL or EXE) for the classes (and other types) contained within and ask these classes for their properties, methods, events and constructors. It is built into the .NET framework and thus always at your service if the .NET support of LV isn't enough. The most important .NET data type when using reflection is System.Type . OK, let's now dissect the code. Sorry about using C# here but I know no better way to explain .NET code. This is what we want to do: GZipStream CreateGZipStream(Stream stream, CompressionMode compressionMode) { // Call the constructor. return new GZipStream(stream, compressionMode); } Since LV doesn't allow us to select this constructor we need another way to get and invoke it. Reflection makes that possible, although the code becomes much more complex. CreateGZipStream.vi is roughly equivalent to the following C# code: GZipStream CreateGZipStream(Stream stream, CompressionMode compressionMode) { // Get the types. Type streamType = typeof(Stream); Type compressionModeType = typeof(CompressionMode); Type gzipStreamType = typeof(GZipStream); // To get the desired constructor we need its argument types and bundle them into an array. Type[] constructorArgTypes = new Type[] { streamType, compressionModeType }; // Get the constructor. ConstructorInfo gzipStreamConstructor = gzipStreamType.GetConstructor(constructorArgTypes); // Bundle the constructor arguments into an array. object[] constructorArgs =new object[] { stream, compressionMode }; // Call the constructor and cast the result. return gzipStreamConstructor.Invoke(constructorArgs) as GZipStream; } Unfortunately LV complicates things a little further: We have no direct equivalent of typeof(). We can work around that by either using GetType() or loading the type from the assembly by name. Using GetType() is easier but it requires a valid .NET reference. Thus we need both: GZipStream CreateGZipStream(Stream stream, CompressionMode compressionMode) { // Get the types. Type streamType = stream.GetType(); Type compressionModeType = compressionMode.GetType(); Type gzipStreamType = compressionModeType.Assembly.GetType("System.IO.Compression.GZIPStream"); // To get the desired constructor we need its argument types and bundle them into an array. Type[] constructorArgTypes =new Type[] { streamType, compressionModeType }; // Get the constructor. ConstructorInfo gzipStreamConstructor = gzipStreamType.GetConstructor(constructorArgTypes); // Bundle the constructor arguments into an array. object[] constructorArgs =new object[] { stream, compressionMode }; // Call the constructor and cast the result. return gzipStreamConstructor.Invoke(constructorArgs) as GZipStream; } But that's still not enough. For LV CompressionMode is an enum, in .NET an enum is a full featured object. So we have also to construct a CompressionMode .NET object in LV and set its enum value. There's no direct equivalent to the 'value__' property in C#, I guess LV does something special here. Now we're ready to invoke the constructor in LV. The snippet again: We construct the CompressionMode object and use its Assembly property to get the GZIPStream Type object. Then we ask for the constructor using the parameter types bundled into an array. Finally we call that constructor with the arguments bundled into an array and cast the result to GZipStream. A note about the style of the code: When it comes to external reference-based code I use a single error wire through all nodes to enforce some kind of control flow. Furthermore it's important to close all open .NET references after using them. I'm using .NET reflection to do things that are not supported by LV for a couple of years now, in my case .NET Remoting with events, see here (no reflective constructor invocation, though).
    2 points
  2. So I have this bug report that AppBuilder fails to build this one particular app whenever the "remove polyVIs and typedefs" option is enabled. The top-level VI breaks during the build. I try some of our usual debug approaches and don't find anything, so I hack up AppBuilder a bit so that when I get to the end of the build, I can open up the broken VIs and see what they look like. And I see this: Where the heck have all the class methods gone? They're in memory at the start, missing at the end. That shouldn't happen! So I set up a trap to detect when the VIs go missing. I'm working in a debug build of LV with a lot of extra guards and logging turned on, so it takes about two hours to run this build. And I get nothing. So I rework my trap, thinking I've coded something wrong. Four times I do this over the course of yesterday, working on other issues while the build runs. Four times -- roughly 8 hours -- nothing. The VIs swear they're all in memory and the caller should know about them. This morning I come in and, for some reason, I happen to double-click on one of those ? nodes. And, lo, the missing VI opens. Say what? Turns out, AppBuilder had stripped all the VI icons out (saves space in the built EXE to ditch all those unneeded images), so they all render as the ? icon. I have no idea what's actually broken, but it ain't that all the class methods have gone away. One wasted day. *head bang* *head bang* *head bang* Yet another reminder -- as if I needed it -- that computers only do what we tell them to do. And they do it very precisely.
    1 point
  3. Thanks for reminding me. I just tested it and yes the TDM Importer Version 18.0.1.7167 (as reported in Excel) now imports my TDMS files without crashing. That was a major pain because I'd uninstall TDM 18.0.0, reinstall TDM 17.x, but in the uninstall some other dependencies were removed which then needed to be reinstalled...which by default installed 18.0.0 again. Oh and it looks like the download page to this add-on was updated yesterday to the new version too. Other fixes in SP1 I've heard are related to VIMs but am unaware of the details.
    1 point
  4. I had a hard time downloading this, but it could be an IT issue on my side. The download would stall, and I'd pause, then resume to get it going again. After installing with default settings, I launched it and got an error "error unable to open resource files". I'll be performing a full uninstall and reinstall. It could be an issue on my end or an issue with the release. I probably should have tested this in a VM first... EDIT: Uninstall and Reinstall fixed it, not sure if that means there is an issue with upgrade or just me.
    1 point
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.