I want to call LabVIEW functions from a python script and trying to understand the memory handling of strings and arrays.
Let's say that I have a COM API created by LabVIEW with a function that look like this:
void Foo(LStrHandle *str)
I want to call this from python and use the library ctypes. I give below the code I have written so far:
from ctypes import*
mydll = cdll.LoadLibrary("MyDll.dll")
# A typedef for the signature of a LStrHandle
LVString = POINTER(POINTER(c_int))
# Cast a LStrHandle to a python string.
# LStrHandle is a int32 that tell the number of chars that following
# direct after the int32 in memory.
def CastLVString(lvValue):
if lvValue and lvValue.contents and lvValue.contents.contents:
# Get the pointer from the pointer to pointer.
lstr = lvValue.contents.contents
# Get the value from the pointer that is the count.
cnt = lstr.value
if cnt > 0:
# Get the bytes after cnt. Number of bytes is defined by cnt.
str_bytes = cast(addressof(lstr) + sizeof(c_int32), POINTER(c_char * cnt))
# Cast the bytes to a string.
return str_bytes.contents.value.decode('utf-8')
return ""
# Wrapper function for COM function Foo.
def Foo():
mydll.Foo.argtypes = [ POINTER(LVString) ]
str = LVString()
mydll.Foo(byref(str))
# Cast the LStrHandle to a python string and return.
return CastLVString(message)
This works, but I wonder if it is correct. Aren't there better ways to handle strings (and vectors)? I wonder how the memory management works. I guess I have to tell LabVIEW that it can free the memory after I read the data. If so, how do I do it? I have seen that the function DSDisposePtr should be used if doing it from C, can this function be used in python?
By the way, the C signature for LStrHandler is as following:
/** @brief Long Pascal-style string types. */
typedef struct {
int32 cnt; /* number of bytes that follow */
uChar str[1]; /* cnt bytes */
} LStr, *LStrPtr, **LStrHandle;