LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Q: Efficient memory allocation for shared C library?

Hello,

I am developing a time critical application running on a PXI-8176 controller. This application will call some third party C code, through a shared library function node in LabVIEW.

Given the time critical nature of the application, what is the best way for the C function to obtain memory?

I think I should initially define the arrays in LabVIEW that the C function will use to pass data in and out. I would pass pointers into the C function, and re-use the same blocks of memory for each iteration of the time critical loop.

Is this the most sensible way to do this?

Should the C code be allowed to declare local variables that go out of scope, or should the C code use a block of memory that LabView pas
ses it (by pointer) as a scratch pad for all temporary local variables?

Thanks in advance,
Frenk
0 Kudos
Message 1 of 7
(4,215 Views)
Hi,
In general, LabVIEW handles memory management for you. When you need to call external code, you should avoid memory manipulation outside of LabVIEW. If you pass a buffer created by LabVIEW to your C code, you'll be fine using it as long as you don't reallocate or deallocate the memory that LabVIEW gave you.

You should keep memory management separate. If your C code requieres memory allocation, its better if you allocate and deallocate it from the C side. But don't mix them up, don't return to LabVIEW a buffer allocated withing your C code.

If you just need a scratch pad internal to your C code, allocate your own memory and release it when you are done inside your C code. Return to LabVIEW just the values that are pertinent.

Another impo
rtant thing. When calling a DLL through the Call Library Node, make sure you configure the node to be reentrant. Under RT, failure to do so causes your C code to be executed under the user interface thread. This will affect the RT scheduler, decrease performance and introduce jitter.

Hope this helps,
Daniel
0 Kudos
Message 2 of 7
(4,215 Views)
Hello,

Thank you for your response Daniel.

Just to clarify, regarding your third paragraph:

If the C code needs scratch memory, wouldn't it be more time efficient to allocate it once in LabVIEW when the program commences, and let the C code use the same block over and over? I would have thought that allowing the C code to allocate and de-allocate memory with each C function call (i.e. each real-time loop iteration) would be time inefficient?

Thanks,
Frenk
0 Kudos
Message 3 of 7
(4,215 Views)
Hello,
You are right about your statement. I think I didn't explain the context I was talking about. If each of your C calls allocates and deallocates memory, then it becomes inefficient.

In some applications I built, I have some init function in my DLL that is called at the beginning of the LabVIEW application. This function allocates memory and holds it in a global pointer inside the DLL. When you call the DLL again through another function call, the same DLL has remained in memory the whole time, so your new function can grab the global pointer and access the data.

This is very common when building drivers in C where you need to hide the context from LabVIEW. Memory is allocated once at the beginning and deallocate at the e
nd of the application. LabVIEW never sees this memory since it is intended for internal use of the DLL.

Let me know if this clarifies.
Daniel
0 Kudos
Message 4 of 7
(4,215 Views)
Hello,

Thanks Daniel. Your reply makes perfect sense. I have no previous experience with DLLs, and didn't think of maintaining memory in the manner that you describe.

If it doesn't take too much of your time, could you briefly outline how the global pointer is maintained in the DLL? I guess I'm having a conceptual difficulty with how DLLs work. I would have thought that each DLL function goes out of scope when execution returns to LabVIEW.

Best Regards,
Frenk
0 Kudos
Message 5 of 7
(4,215 Views)
Hello,
The idea is to have some variable that is global to the DLL. Any function inside the DLL can access that variable. Since the DLL is loaded into memory and attached to the process on its first call, data stored in global space retains its value in subsequent calls to the DLL.
Here's a small piece of code that illustrates this:

/* Global data */
double *myGlobalData = NULL;

//Allocate data. Size is given in bytes
int initData(int dataSize)
{
myGlobalData = malloc(dataSize);

return 0; //add error handling
}

//Clear allocated data
int clearData(int dataSize)
{
if (myGlobalData)
{
free (myGlobalData);
myGlobalData = NULL;
}

return 0;
}


From LabVIEW you can call the 'in
itData' function to allocate scratch memory and 'clearData' to clean up at the end of your application. Other functions in your DLL can reference the 'myGlobalData' pointer to read or write data.

I'm using dynamic memory allocation in my example, but using fixed sized buffer would work too (for example creating a global array of fixed size).

Let me know if this clarifies,
Daniel
0 Kudos
Message 6 of 7
(4,215 Views)
Hello,

Thank you very much Daniel. Your code is very clear, and I understand the concept now.

I am running in LabView real-time, and I wonder if maintaining a global pointer in the DLL would violate the thread-safe (reentrant) requirement for running the DLL code in the time-critical thread? Code that is not thread-safe is run in the user interface thread.

Of course, since the LabVIEW side of the application is written by me, I can make sure that the DLL init function is only called after a proper call of the clear function. That is, that there is only one LabVIEW thread using the DLL at a time.

Thanks again for taking the time to post the example code. Its much appreciated.

Best Regards,
Frenk
0 Kudos
Message 7 of 7
(4,215 Views)