09-12-2024 04:38 AM
Hi,
I have an application that I want to split up because of its size. This way, parts can be "switched off" when they are not currently needed and the EXE remains compact and not all VIs are loaded into memory. I initially thought of dynamic VI handlers, since I wouldn't have to change much here, except that I always pack all VIs into the EXE, right?
But now I would like to know whether I can also make executables from my daemons and whether my user events and queues can still be used (I read something about VI servers together with action engines). I have already read data from an EXE using VI servers, but how can I use functions that normally only work in the EXE itself?
Many thanks for any suggestions.
Solved! Go to Solution.
09-12-2024 05:26 AM - edited 09-12-2024 05:27 AM
No, LabVIEW refnums are private to a particular application context. That goes even further than executables. Each target in a project is its own application context and they can’t see each other’s refnums.
You’ll have to resort to real inter process communication such as network streams, shared variables or your own TCP/IP communication protocol.
09-12-2024 10:13 AM
Hi,
I found this old post from mikeporter
Solved: path of vi in exe - NI Community
He wrote, you "Also you can essentially use queues and events between executables"...but how to do with VI-server?
Or...how can I replace user-events with commands over TCP? Maybe queues I can manage with network-streams. But replace action-engines , that are used in several VI`s (and later executables) could be difficult ...mmhh
So this 3 items I think are to check, events, queues and action-engines...thanks for suggestions
09-12-2024 01:36 PM
You may want to consider looking into PPLs, i.e. "Packed project libraries", LVLIBP files.
Fair warning, these can add as many problems as they solve, it's not just a simple switch you can flip. Once you solve them you will have smaller builds and more modular code, but it is a big pain to get there.
Out of curiosity, how big is your program now? Are you actually getting to the point where the size causes problems, or does it just "feel" too big?
09-13-2024 05:17 AM - edited 09-13-2024 05:35 AM
Hi Kyle,
to big means, my executable has reached 43MB. And inside there are a lot of (relative loose coupled) daemons, which I don´t need all the time. For example, there is included a daemon for controlling keithley-multimeter, but a lot of collegues don´t need this device. And actually I put all of them into idle-state. And sometimes I got errors for too fast reading/writing.
Maybe I should try again to use dynamically calling VI´s, so that they don´t need memory/CPU. That seem´s to be the easiest way, but not for the future...
One daemon I´ve changed 1 year ago for trying out to TCP-communication. Thats ok for some of the daemons and they can stand alone at the end as executable. But most daemons using user-events and queues for communication...and therefore I need a solution...
09-13-2024 11:35 AM
If you're willing to re-architect a fair amount of your messaging, you could look into adopting the MQTT protocol. I don't use it, but one of my co-workers does and he made it work.
If you do a web search for "MQTT LabVIEW" there should be a number of videos that come up about it from old presentations given during NI week or similar events. There's already open source code for the server and basic communications interactions, so you'd just be adapting it to your code.
Just in general I would note that 43 megs for an EXE isn't super large as LabVIEW goes. The only application I have that has grown so large it occasionally gives memory errors on build comes in at 90+ megs.
09-13-2024 01:39 PM
Hi,
I use MQTT actually (configuration-vi and daemon) for publishing and subscribing data to/from our cloud...but at the end its TCP too.
But how can I fire events by TCP or how can I replace my events with TCP/VI-Server/...mh.
Or, if you say 42MB isn´t as big as I thougth, I´ll use dynamic loading of vi´s?...
Today I cant see, what extension came next from my department...???!!!
09-13-2024 02:12 PM
@Tanchris wrote:
But how can I fire events by TCP or how can I replace my events with TCP/VI-Server/...mh.
With MQTT or any other way to communicate between applications, or between separate execution spaces in the same application, the general process would be the same.
I'm going to assume you're using user events for everything here. If you're using either the built-in events like value changes on button presses, or events that fire callback VIs such as .NET events, then you must convert those to user events.
The user event in LabVIEW essentially has 3 subcomponents in it that you would need to ensure get copied over TCP.
1. The reference (data type + pointer to a memory address where events can be sent).
2. The registrations
3. The data sent with each event
For the reference, you'd need to essentially replace that with a predefined header of some kind instead of passing around an event wire or having a global VI where you store it. In MQTT this would probably be either an "Events" topic in general (with a header on the data afterwards to designate which event), or a specific topic per event. For any other TCP communications, whatever you set up to receive data would need to look at the header and redirect it to local code that processes incoming event data. In both cases, you'd need to predefine the event data on both ends, probably by having a type definition in a shared library that both applications have to sync up on and use.
For the registrations, with MQTT that would be setting up subscriptions to any Event channel. For both MQTT and any other custom TCP solution, that could be handled via internal registrations of user events that are broadcast whenever a data packet comes in to the subscription. It could also directly just call one VI if the application only has one place for event registration to be sent to.
For the data itself, there's two things to worry about.
One is the fact that events may not be handled immediately, so whatever you do for the registrations you need to make sure that the data is saved until it's ready to be pulled by whatever registrations you implemented. If you use local user event registrations per separate application, it's already handled. If not, I would recommend a queue or similar lossless FIFO architecture to be sure every event plus its data gets delivered.
The second thing is how to encode the data.
The easiest way is to just use "Flatten to string" before sending over TCP, and "Unflatten from string" on the other end. This does require absolute synchronization of your data type, though. You have to be very careful to be sure that every sender and every receiver understand everything you flatten the same way, so never getting out of sync on type definitions or library versions. If you try the unthinkable and send class data, good luck keeping that synced up if you use any sort of inheritance hierarchy. Flattening to a string also allows you very little debugging just by examining the messages. It can be fast, though (both to set up in code and the execution time of the flatten/unflatten methods).
An alternate way would be to encode everything in readable ASCII somehow, such as JSON or XML. This makes it a lot easier to have versioning mismatches not result in instant failure, and also a lot easier to add debugging if you snoop on the message traffic. However, you will have to create your own methods for packing and unpacking those ASCII structures, and the execution time for large messages can get prohibitively large if you need to pass around million-element numeric arrays or things like that.
09-13-2024 04:08 PM
There's also the new gRPC stuff which (if I understand right) sounds like it might help couple some things:
https://github.com/ni/grpc-labview
Also, if you wanted to refactor into the Actor Framework, there are Network Endpoint Actors that can communicate not just on one computer but across a network as well.
09-17-2024 05:05 PM
You can sort of use references from another process over VI server. The "remote" references can't be used in the local application, but VI server lets you run VIs in the context of the remote app so they can be used that way.
I attached a demo you can use by building/running the "server" and then running "client.vi" in the IDE.
The key bit is that the "foreign" reference is only ever actually used by VIs that run in the foreign app.