Jump to content

candidus

Members
  • Posts

    109
  • Joined

  • Last visited

  • Days Won

    11

Posts posted by candidus

  1. 17 hours ago, smithd said:

    https://dotnetcademy.net/Learn/4/Pages/1

    Its roughly analogous to combination of VI server/scripting + lvoop class loading + variant data type inspection VIs + openg type code inspection VIs...except with a more consistent design

    Great article, thanks! And a pretty cool way to explain things in LV terms:thumbup1:

     

    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:

    CreateGZipStream.thumb.png.ce1f851e5a2f70b065f73a1ac391292b.png

    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).

     

     

     

     

     

    • Like 1
    • Thanks 1
  2. Benoit, sorry about the missing documentation. The snippet above is just the constructor call

    new GZipStream(Stream stream, CompressionLevel compressionLevel)

    expressed via .NET reflection. Yes, it is that complicated but at least it's possible.

    For a more complete example see the ZIP file appended to my first post. I will write a more detailed explanation tomorrow.

  3. On 3.10.2018 at 11:35 PM, hooovahh said:

    You probably already saw a discussion on Code Sharing, which has no conclusion yet.  My opinion is if it is stable and good and you don't expect much changes, submit it to the Code Repository here (package preferred).  If this is still in a state of flux and development, a site better equipped with change management like BitBucket or GitHub would probably be better.  That being said this is a fine place to start discussions and suggestions, and can be moved to Code In Development at your request.

    I did it: Here is the URL to the GitHub repository: https://github.com/mus-candidus/StyledText

    Please move this thread to "Code in Development".

  4. 23 hours ago, hooovahh said:

    I've been using LVMark for several years.  It isn't HTML but a type of markdown format.  Years ago there was another attempt called Formatter which does look like HTML.

    Cool, if I knew that before I probably didn't create my own library. Probably I used the wrong keywords for my search on LAVA.

    But now that my library exists, what to do with it? Submit it to the CR? Create a GitHub repository? Do both? I'm unsure...

  5. There is a reason to refactor: I have to add more features and I don't want my toplelvel VI to become any bigger - currently it has a huge block diagram...

     

    On 26.8.2017 at 6:21 PM, drjdpowell said:

    The other school is to use a single User Event to carry all messages, using something generic like a string “message label” and a Variant “data” payload.

    So this is not a lot of work, or at least, not more than any other possible method.

    That's it! I began to experiment with an event containing a variant-based lookup table, then I looked at Messenger Library and saw that all I need is already there.

    Thanks!

  6. I have to decouple the UI part of a medium size application (approx. 2000 VIs) from its core.

    When we created the application it was a simple state machine.
    Later we realized that some operations must be asynchronous
    so we added an event-based control loop that controls the state machine
    via user events. But it was still a single VI and over the years it grew bigger...
    Now I decided to move the state machine (approx. 70 states) into a subVI but since
    there never was a separation between the UI part and the non-UI part I now
    need a way to access the UI controls (approx. 40 controls) from the state machine.


    Currently I see the following options:

    1) User events from/to the state machine. This seems to be a quite clean
    approach but means a lot of work.

    2) Use something like Actor Framework. Probably the most clean approach but
    even more work.

    3) Get/Set Control Values by Index. I prefer that over Get/Set Control Value
    because I often have to read/write several controls at once. I can easily
    encapsulate this in a nice class that maps my control names to indices.

    4) Put the control refnums into a cluster and pass that to the state machine subVI.
    This is the approach I dislike the most. I already decided not to do it that way.

    Currently I like 3) best but I have mixed feelings about it:
    - It seems odd to use control access to separate application parts. Maybe that's just me but it feels wrong...
    - I have controls of which I have to access other properties than the value so I definitely need events here.
    - Searching here on LAVA brought nothing about Get/Set Control Values by Index which disturbs me a little bit.

    Do you have any any advice for me? Do I miss something important?

    Thanks in advance,

    candidus
     

  7. There was such a thing in the old times of LV6 .

    Here is what I remember (This was nearly 15 years ago, my memory about this stuff is dim):

    LV player was able to run signed VIs, you were even able to see (but not edit) their block diagrams.

    To sign a VI you needed a special tool that required a LV6 Professional Development System.

    Without LV6 and this signing tool you won't be able to do anything useful with the player.

     

    I don't see a reason to resurrect this old piece of software, except for nostalgia :-)

    • Like 1
×
×
  • Create New...

Important Information

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