LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Malleable VIs break in executable context

We recently needed to add some string formatting to escape special characters prior to building an SQL query. The strings were coming from several different cluster typdefs, so it felt like a good opportunity to make a malleable VI that could modify any strings with a given cluster (including nested clusters).

 

To support the nested-cluster scenarios, we introduced recursion in the function. That meant there was a fundamental disconnect: a malleable must be inlined (and thus a preallocated clone), whereas recursion requires shared-clone reentrancy. Managed to resolve this in the development environment by having a wrapping malleable VI that calls a recursible subvi. This was functioning well, and we created a suite of unit tests to verify the behavior across many different incoming datatypes (strings, clusters containing strings, nested clusters, etc).

 

However, when we built the executable, it would open up broken. The build process was successful, but the exe would open broken with the following error:

"VI has an error of type E348. The full development version of LabVIEW is required to fix the errors."

 

Lost a lot of time trying to figure out the problem, but eventually traced it to the malleable VI by attaching debugger to the executable. 

 

Pointing this out here in case anyone else stumbles on this sort of problem.

 

But also curious: has anyone else come up with a solution for performing recursive actions on cluster elements using malleables? In the past, I have leveraged queues to avoid recursive VI calls when stepping through cluster elements, but I wasn't able to come up with a way to do that here that could effectively modify the elements in-place...

0 Kudos
Message 1 of 4
(1,363 Views)

I have a very similar situation, where I have a malleable (wrapper) VI that can take any nested cluster structure, fill its values depending on other inputs and then output the updated data using the same structure. Inside the malleable VI, there is a non-reentrant core function that takes variants and that also contains lots of recursive subVIs (to handle arbitrary complex nested cluster structures).

 

When executing the application (in dev environment), I had periods where calling this function systematically crashed LV with an internal error. I finally found that it happens every time I modify the core function without recompiling my production VIs (that use the malleable function). It seems to me that it is a bug where malleable VIs do not always trigger recompliation of their caller when a subVI in their own call hierarchy is modified.

 

So my workaround was to create a script that recompiles every caller of my core function, which I run each time i modify it. See the code attached so you could try by yourself. You could as well put it in a prebuild VI to automate it completely.

0 Kudos
Message 2 of 4
(1,281 Views)

@TurboPhil wrote:

To support the nested-cluster scenarios, we introduced recursion in the function. That meant there was a fundamental disconnect: a malleable must be inlined (and thus a preallocated clone), whereas recursion requires shared-clone reentrancy. Managed to resolve this in the development environment by having a wrapping malleable VI that calls a recursible subvi. This was functioning well,


Could you elaborate on that?

 

Do you mean you have a vim to adapt to types, and then a normal VI that deals with variants or something?

 

I did have .vims (just a simple sync.vim) break my build process. Without any clear error, so I had to split my project and iteratively do a binary search for the problem... Lost hours on it.

0 Kudos
Message 3 of 4
(1,248 Views)

wiebe@CARYA wrote:

@TurboPhil wrote:

To support the nested-cluster scenarios, we introduced recursion in the function. That meant there was a fundamental disconnect: a malleable must be inlined (and thus a preallocated clone), whereas recursion requires shared-clone reentrancy. Managed to resolve this in the development environment by having a wrapping malleable VI that calls a recursible subvi. This was functioning well,


Could you elaborate on that?

 

Do you mean you have a vim to adapt to types, and then a normal VI that deals with variants or something?


My original attempt (which again, I ended up abandoning because it failed to work in built exe) was to create the recursive cluster-modifying algorithm using variants, and then wrapping it in a .vim that would cast the variant back to the original datatype.

 

In my case, I wanted to find all strings inside of an arbitrarily-nested cluster, and do some escaping of special characters in each of those strings. So I started with a function that accepted a variant input, and then leveraged the NI_Data Type.lvlib:Get Type Information.vi to determine datatype; if it was a string, it would cast variant to string and then perform the necessary escaping; if it was a cluster, it would recurse through the cluster elements. Once I had that much working, I wrapped it in a .vim to do a variant-to-data back to the original datatype, so I could drop down a single VI anywhere that I needed to do this escaping.

 

Once I found that it failed in the exe environment, I gave up on the .vim wrapper, and just used the variant-based functions to convert and did an explicit downstream variant-to-data at every callsite. Less elegant, but got the job done. Sad that the .vim dream didn't live up to its promise here.

0 Kudos
Message 4 of 4
(1,243 Views)