‎04-10-2024 04:49 PM
I apologize in advance, as I think this is more of a Python question than a LabVIEW question. But, I think someone here probably has experience doing what I want to do.
I'm building a DLL with LabVIEW, and would like to test it with something else. I don't have much experience with other languages, so I chose to try Python.
I started with a simple example of adding two integers together, and that worked fine.
Now I've got a VI / function which just has a File Path control input. When I try to call this from Python, I'm getting access violation errors, so I think I'm passing in the file path incorrectly.
Python code:
import ctypes
dll = ctypes.cdll.LoadLibrary("C:\LabVIEW 2016\Misc\DLL Test\Builds\Build2\Build2.dll")
dll.ReadFile.argtypes = (ctypes.c_char_p,)
dll.ReadFile.restype = None
FilePath = b"C:\Users\gjacob\Desktop\File Parking\example.txt"
dll.ReadFile(FilePath)
I get the following error: OSError: exception: access violation reading 0x555C3A43
The header file for Build2.dll is below:
#include "extcode.h"
#pragma pack(push)
#pragma pack(1)
#ifdef __cplusplus
extern "C" {
#endif
/*!
* ReadFile
*/
void __cdecl ReadFile(Path *FilePath);
MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);
#ifdef __cplusplus
} // extern "C"
#endif
#pragma pack(pop)
Thank you in advance!
Solved! Go to Solution.
‎04-10-2024 08:05 PM
Are you using the same bitness for both LabVIEW and Python? 64-bit DLL and 64-bit Python work for me.
import os
import ctypes
dllPath = os.path.join(os.getcwd(), "lv-build", "lv-ReadFile.dll")
dll = ctypes.cdll.LoadLibrary(dllPath)
dll.ReadFile.argtypes = (ctypes.c_char_p,)
# dll.ReadFile.restype = None
filePath = os.path.join(os.getcwd(), "Test.txt").encode('utf-8')
count = dll.ReadFile(filePath)
print(count)
‎04-11-2024 11:15 AM
Hi ZYOng, yes I am using 32-bit LabVIEW and Python 3.11. When I first tried I was using 64-bit Python by accident and get an error: %1 is not a valid windows process. When I switched to 32-bit I was able to get a simple use case of adding two integers to work. I've tried to form the FilePath exactly the same as yours, but I am still getting the access violation. The terminal output looks like this:
b'C:\\Users\\gjacob\\PycharmProjects\\Test LabVIEW DLL\\Test.txt'
Traceback (most recent call last):
File "C:\Users\gjacob\PycharmProjects\Test LabVIEW DLL\simple_test_2.py", line 11, in <module>
dll.ReadFile(FilePath)
OSError: exception: access violation reading 0x555C3A43
Process finished with exit code 1
The first line is the printed FilePath. Below is the Python File:
import ctypes
import os
dll = ctypes.cdll.LoadLibrary("C:\LabVIEW 2016\Misc\DLL Test\Builds\Build2\Build2.dll")
dll.ReadFile.argtypes = (ctypes.c_char_p,)
dll.ReadFile.restype = None
FilePath = os.path.join(os.getcwd(), "Test.txt").encode('utf-8')
print(FilePath)
dll.ReadFile(FilePath)
‎04-11-2024 11:16 AM - edited ‎04-11-2024 11:18 AM
A LabVIEW path is NOT a string and neither a C string pointer. Trying to match any sort of LabVIEW handle (Array, String and Path) with Python ctypes is not only an exercise in advanced C compiler details but pretty much an exercise in vain since you can’t match the management contract of LabVIEW handles with ctypes as it is.
Make this a string on the VI frontpanel and configure it as C string pointer in the DLL function configuration of the DLL Build dialog and then it will match with your current ctypes declaration in Python.
‎04-11-2024 11:25 AM
I guess you didn't open my attachment. I forgot to mention that I use String Control instead of File Path Control.
‎04-11-2024 11:31 AM
Ah thank you both. I was previously able to pass string data to a different DLL, so this should not be a problem.
This is one of the reasons I want to test the DLL with something besides LabVIEW, to figure out where the pain points are.
I'll get rid of the filepath controls and switch them to strings. Thanks!
‎04-11-2024 12:11 PM
If anyone stumbles across this trying to figure out how to read a string output from a LabVIEW-built DLL in Python, you can do the following.
The example VI takes in the "FilePath" and outputs the file name as "Name".
When you build this function into a DLL, it will automatically create a length parameter for "Name". The Python file is shown below. It doesn't seem to matter whether you input FilePath or ctypes.c_char_p(FilePath) into the function call. I think due to the argtypes definition it knows how to send the string.
import ctypes
import os
dll = ctypes.cdll.LoadLibrary("C:\LabVIEW 2016\Misc\DLL Test\Builds\Build2\Build2.dll")
# void __cdecl ReadFile(char FilePath[], char Name[], int32_t len);
dll.ReadFile.argtypes = (ctypes.c_char_p,
ctypes.c_char_p,
ctypes.c_int)
dll.ReadFile.restype = None
FilePath = b'C:\\Users\\gjacob\\PycharmProjects\\Test LabVIEW DLL\\Test.txt'
len = 1024
Name = ctypes.create_string_buffer(len)
# dll.ReadFile(ctypes.c_char_p(FilePath), Name, len)
dll.ReadFile(FilePath, Name, len)
print(FilePath)
print(Name.value)