Magnus Österlund Posted July 1, 2023 Report Share Posted July 1, 2023 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; Quote Link to comment
Rolf Kalbermatter Posted July 10, 2023 Report Share Posted July 10, 2023 (edited) It looks fairly ok. But you have a problem. You need to free that handle and that is not trivial. You need to call DSDisposeHdl() from the LabVIEW manager functions, however it depends on various things as to what DLL that function needs to come from. Most likely however does your DLL already export a helper function. Have you checked the header for your DLL? Isn’t there an additional function named DisposeLStr or similar exported? Calling that correctly will properly deallocate the handle after you are done with it. One small correction, COM either means a serial communication port or the underlying technology for ActiveX (Component Object Model). There is a separate Python module to handle COM interfaces but that works differently. Here you simply call classic DLL functions. Edited July 10, 2023 by Rolf Kalbermatter Quote Link to comment
Magnus Österlund Posted July 14, 2023 Author Report Share Posted July 14, 2023 I have searched in all exported header files. I can find exported functions to deallocate arrays of different types, but not strings. Quote Link to comment
Rolf Kalbermatter Posted July 14, 2023 Report Share Posted July 14, 2023 (edited) Post your LabVIEW project for the DLL, the DLL and its header. And please do a save for previous for2020 or earlier. Edited July 14, 2023 by Rolf Kalbermatter Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.