LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Call DLL via Python: Pass String to String Cluster

Hi, 

 

we have built a LabVIEW DLL with the following C Header-File. 

#ifdef __cplusplus
extern "C" {
#endif
typedef uint8_t  Enum;
typedef struct {
	LStrHandle Channel;
	Enum ACDC;
	double AmplitudeVA;
	double FrequencyHz;
} Pin;

Now i try to pass some values with the help of this documentation: 

https://docs.python.org/3/library/ctypes.html#module-ctypes

 

I succeeded to pass values for the frequency and amplitude but in case of the enumeration and LStrHandle  i got some strange errors. Unfortunately, i couldn't find some examples for those two data types. I succeeded to pass a string to the DLL, but the string control was not a part of a Cluster, like in this case.

 

Now my question:

Is it possible to pass a string to a string control which is part of a Cluster. If yes, how? 

 

Thanks,

John Lee

0 Kudos
Message 1 of 3
(3,254 Views)

This isn't exactly the same, but perhaps it is useful - I tested this to allow me to pass something like error clusters from C++ to LabVIEW via Event Structure:

 

 

#pragma pack(1)
typedef struct _EventSend
{
	_EventSend()
	{
		code = 0;
		severity = 2;
		message = nullptr;
	}
	int code;
	unsigned short severity; // Uses a U16 in LabVIEW for the enum
// Make sure the class matches the enum typedef. LStrHandle message; } EVENT_SEND; #pragma pack() EVENT_SEND eventStruct; void LabVIEW_ErrorEvent::sendErrorEvent(int errorCode, Severity severity, std::string message) { LabVIEW_Info::init(); eventStruct.code = errorCode; eventStruct.severity = static_cast<unsigned short>(severity); // Allocate a LabVIEW String Handle LStrHandle newStringHandle = CreateLabVIEWString(message); eventStruct.message = newStringHandle; // Send the event LabVIEW_Info::f_PostLVUserEvent(*eventRef, static_cast<void *>(&eventStruct)); } LStrHandle CreateLabVIEWString(std::string message) { // Calculate needed memory space int stringLength = message.length(); const unsigned int memSize = sizeof(int32) + stringLength * sizeof(uChar); LStrHandle handle = reinterpret_cast<LStrHandle>(LabVIEW_Info::f_DSNewHandle(memSize)); // Empties the buffer memset(LStrBuf(*handle), '\0', memSize); // Add data sprintf(reinterpret_cast<char*>(LStrBuf(*handle)), "%s", message.c_str()); // Inform the LabVIEW string handle about the size of the string LStrLen(*handle) = stringLength; return handle; }

The f_DSNewHandle and f_PostLVUserEvent are just wrappers around the C .lib functions available with LabVIEW (to allow DLLs, if I recall correctly).

 

Here you can see how I created the strings using the LabVIEW library to allocate the memory and pass the value. Probably you're already doing this for the non-cluster case, but perhaps there's some small detail that will help if it's the same in Python.

 


GCentral
0 Kudos
Message 2 of 3
(3,219 Views)

This is going to be brittle at best. LabVIEW handles are memory buffers that need to follow a very specific managed contract. This means they need to be created, resized and deallocated from the same LabVIEW memory manager kernel. You can not change in which memory manger kernel de LabVIEW DLL runs, that is determined at the time the DLL is loaded by initializing the according LabVIEW runtime system version that matches the LabVIEW version used to create the DLL. So you would have to somehow determine that runtime DLL (very tricky to get right) and then dynamically link to the according DSNewHandle() functions in that lvrt.dll.

The most simple approach would be to avoid having to use LabVIEW handles in the API. They only really make any sense if the DLL function needs to resize them somehow in place and return them back to the caller. If the function only needs to read that buffer it is much better to change the API and pass that buffer as a separate C string pointer. That you can allocate in ctypes, pass to the function and then deallocate afterwards without having to try to also get the correct LabVIEW memory manager functions. ctypes doesn't and can't know about LabVIEW specific datatypes and even less about the necessary memory manager functions needed to handle them properly.

 

Using ctypes you could theoretically create helper functions that can create such handles but there remains the problem to determine the correct LabVIEW runtime to link to to load the according functions from. An alternative would be to add additional VI functions to the DLL that are initializing and deallocating the according variables for you but that will require you to quite some extra work on the DLL side to add these functions which are basically more or less programming C in LabVIEW but on a fairly low level, and then additional work on the Python side to interface with ctypes properly to these extra functions too! Basically complicating the whole thing by factors and creating even more work for you to figure out, requiring knowledge that even normal C programmers aren't able to just produce at a fingersnap.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 3 of 3
(3,208 Views)