convert c function with varargs in ellipsis style to python equivalent using ctypes

Viewed 87

I have a c function with the following signautre

func(enum_type level, const char* function, const int line, const char* file, const char* msg, ...)

What would be the equivalent param types that need to be passed in the ctypes decorator call?

I tried something like this

@CFUNCTYPE(None, level, POINTER(c_char), c_int, POINTER(c_char), POINTER(c_char),"...")

since "..." is not a ctypes type not sure how to handle this

1 Answers

Don't specify anything for .... ctypes allows extra parameters, but you may have to hint how to marshal the parameters correctly. Without specific argtypes, ctypes will assume conversion to c_int for int parameters, c_char_p for bytes, c_wchar_p for str and either fail or do the wrong thing for other parameters. Do the conversion manually if needed. Example:

import ctypes as ct

dll = ct.CDLL('msvcrt')                 # For printf/wprintf on Windows
dll.wprintf.argtypes = ct.c_wchar_p,    # int wprintf(const wchar_t*, ...)
dll.wprintf.restype = ct.c_int
dll.printf.argtypes = ct.c_char_p,      # int printf(const char*, ...)
dll.printf.restype = ct.c_int

dll.wprintf("%s, %d, %lf\n", "hello", 123, ct.c_double(3.14))
handle = 0x123456789 # >32-bit.  Pointers are 64-bit on my system.
dll.wprintf("%p\n", ct.c_void_p(handle))
dll.printf(b"%s, %s!\n", b'Hello', b'world')

Output:

hello, 123, 3.140000
0000000123456789
Hello, world!

If you remove the ct.c_double() or ct.c_void_p conversions, ctypes complains it doesn't know how to marshal the float, and complains that the int is too big since it is larger than a c_int can hold.

Related