LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Memory Allocation for DLLs

I've been learning how to create DLLs in C to use in LabVIEW, mostly for fun.

 

In the examples from NI examples\Connectivity\Libraries and Executables\External Code (DLL) Execution.vi, they show how to allocate memory for the output. From the example that reverses an input string, they show to allocate memory for an equal-length string for the output:

JeremyPeterson_0-1738936990158.png

 

That makes perfect sense. My main question: is there a reason this is strictly necessary? I understand that I need to allocate memory if the output was a different size or shape. But for the example of reversing a string, is there any reason you can't operate directly on the input?

 

For example, I re-created the function without the separate output memory:

__declspec(dllexport) void reverseString(char *str)
{
  int i, length;
  length = (int)strlen(str);

  char strBuf[length + 1];
  strcpy(strBuf,str);

  for(i=0; i<length; i+=1)
    str[length-i-1] = strBuf[i];
}

And I can call it like so:

JeremyPeterson_1-1738937512457.png

Works great!

JeremyPeterson_3-1738937774288.png

 

 

I thought maybe that was a bad idea because I was directly overwriting the input, and maybe I need it later. But The value of the control stays fine, so it seems like LabVIEW is allocating new memory for me automatically, or maybe I just don't understand how it works fully:

JeremyPeterson_2-1738937671004.png

(Probe still contains the unaltered contents of String In)

 

Any explanations are greatly appreciated! I'm hoping to fully understand these simple cases, so I have a decent chance when I do anything more complicated.

 

I've attached the VI (2019) and DLL (CodeBlocks project and 32-bit compiled) I made, if anyone wants to take a look. The C code is in CodeBlocks\LabVIEW DLL Example\main.c. If anyone spots anything else I did wrong, I'd love to hear!

0 Kudos
Message 1 of 3
(130 Views)

You are diving head first into the low level intricacies of LabVIEW memory management and it can get complicated.

 

In principle you are right, there is no need to create a second parameter nor a buffer for it. That example is not meant to show best practice for implementing a reverse array algorithm, but rather show the various aspects of proper memory management when interfacing to a DLL.

 

What you are observing is the fact that LabVIEW sees that the right side of the parameter is wired (so obviously used) AND that you haven't checked the Constant checkbox in the configuration for that parameter. So LabVIEW creates a copy to pass to the function since you told it, no this parameter is not constant and the function may therefore modify it to be used in the output.

 

If you had checked the Constant checkbox, LabVIEW would trust you to tell it the truth and will usually (there is no guarantee for that) not allocate a copy, even if you branch the wire away before it passes to the DLL node. And you will suddenly see the value in the wire being different, despite that you branched it off. That is because you told LabVIEW, no problem my DLL function is not going to modify that parameter and LabVIEW believes you and does not allocate a copy for optimization reason and tada, you get bad results.

 

So the takeaways from this:

 

- Those examples are not meant to show you the best and optimal way to do a reverse array algorithm, but instead tries to show you how proper memory management should be done. The reverse array (string) is just a trivial to implement algorithme, rather than trying to devise some other more complicated thing.

 

- What you tell LabVIEW in the Call Library Node does matter a lot. LabVIEW has absolutely no way to verify that what you tell it is true, it has to believe you blind. A DLL does not export anything besides the function pointer. If that function pointer is a function taking 50 parameters, or none at all, is entirely depending on how it was programmed. Same about what datatypes each parameter has and how memory should be handled for each of them. LabVIEW can not verify anything of these things and simply has to trust that the configuration tells the truth and that the programmer has observed the necessary memory management rules such as preallocating large enough buffers for the various parameters.

Rolf Kalbermatter
My Blog
Message 2 of 3
(94 Views)

@Jeremy.Peterson wrote:

But The value of the control stays fine, so it seems like LabVIEW is allocating new memory for me automatically, or maybe I just don't understand how it works fully:

JeremyPeterson_2-1738937671004.png

(Probe still contains the unaltered contents of String In)


Front panel element have their own memory and transfer buffer to buffer values for asynchronous updates in the UI thread. That memory cannot be reused as output. It would be really bad if a control would change value as a function of a downstream operation. That would break everything and as you can see, the LabVIEW compiler is smart enough. 😄

 

You can see that a buffer allocation must be made (menu...tools...profile..show buffer allocations).

 

altenbach_0-1738957607655.png

 

Message 3 of 3
(76 Views)