I have a function in a Windows DLL:
extern "C" {
bool __declspec(dllexport) PublicOpenFile(const char * pFilePath)
{
return SomeOtherFunc(pFilePath);
}
}
which I am trying to invoke from a Python 3.12.9 script as follows:
import ctypes
lib = ctypes.cdll.LoadLibrary('The.dll')
funcOpenFile = lib.PublicOpenFile
funcOpenFile.argtypes = [ctypes.c_char_p]
funcOpenFile.restype = ctypes.c_bool
fileName = "TheOutput.txt"
result = funcOpenFile(fileName)
print(result)
and am getting:
Traceback (most recent call last):
File "C:\Python_Cpp.py", line 9, in <module>
result = funcOpenFile(fileName)
^^^^^^^^^^^^^^^^^^^^^^
ctypes.ArgumentError: argument 1: TypeError: wrong type
What am I doing wrong?
Many thanks
c_char_p
corresponds to a bytes
object. "TheOutput.txt"
is a str
object and would be used for the C wchar_t*
type (ctypes c_wchar_p
).
Use a bytes
object with c_char_p
, e.g. b"TheOutput.txt"
.
Note that on Windows, C functions that use char*
for file paths expect them to be ANSI-encoded. For your all-ASCII filename using a literal bytes
works, but for a filename like 'pingüino.jpg'
the ü
isn't supported in byte strings. Use a str
and encode it to bytes
with 'pingüino.jpg'.encode('ansi')
in that case.
Example using C FILE *fopen(const char *filename, const char *mode)
and Python 3.13:
>>> import ctypes as ct
>>> clib = ct.CDLL('msvcrt')
>>> clib.fopen.argtypes = ct.c_char_p, ct.c_char_p
>>> clib.fopen.restype = ct.c_void_p
>>> clib.fopen(b'pingüino.jpg', b'r')
File "<python-input-11>", line 1
clib.fopen(b'pingüino.jpg', b'r')
^^^^^^^^^^^^^^^
SyntaxError: bytes can only contain ASCII literal characters
>>> clib.fopen('pingüino.jpg'.encode('ansi'), b'r')
140704303274784
If you can change the code, using C wchar_t*
and ctypes c_wchar_p
enables using any supported Unicode character in a filename and str
can be passed.
Example using C FILE *_wfopen(const wchar_t *filename, const wchar_t *mode)
:
>>> import ctypes as ct
>>> clib = ct.CDLL('msvcrt')
>>> clib._wfopen.argtypes = ct.c_wchar_p, ct.c_wchar_p
>>> clib._wfopen.restype = ct.c_void_p
>>> clib._wfopen('pingüino.jpg', 'r')
140704303274928