如何使用 ctypes.create_string_buffer 将其作为 C 函数的 char * 参数传递?

How do I use ctypes.create_string_buffer to pass it as a char * argument for a C function?

我有一个 C/C++ dll 函数:

int get_camera_info(char * description, char * serial_number, char * manufacturer)

此函数接受参数并修改它们,以便您可以打印它们。我正在尝试通过 ctypes 使用来自 Python 的这个 DLL。我想我需要使用 ctypes.create_string_buffer 来创建一个空缓冲区,以便我有一个可变对象。但是,我该怎么做才能将其作为参数传递然后检索数据?

我需要使用 cast(buffer_object, c_char_p_object) 吗?这与最初创建和传递 c_char_p 对象有什么不同?我不太了解 C/C++,但也许我应该使用 ctypes.POINTER.

我的问题是,在将 c_char_p 类型的对象作为参数传递后,出现错误:OSError: exception: access violation reading 0x00000000.

如果您需要任何帮助来理解我的问题,尽管问。或者,如果您认为我最好使用 cppyy 之类的东西,那么我也需要帮助。 :)

这是基础知识。虽然在这种情况下没有严格要求,但正确设置 .argtypes.restype 有助于 ctypes 正确编组参数并检测错误传递的参数。

类似于将数组传递给C函数,create_string_buffer returns一个c_char_Array_array_<i>size</i>对象,但它被编组为指向它的第一个元素 (c_char_p) 的指针,因此它符合 .argtypes 赋值。

如果没有 .argtypes 赋值,传递不正确的内容(例如 intcreate_unicode_buffer() 数组将会崩溃或产生错误结果。但正确定义它会捕获这些错误并引发异常。

test.c

#include <string.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

API int get_camera_info(char * description, char * serial_number, char * manufacturer)
{
    strcpy(description, "Description");
    strcpy(serial_number, "12345678");
    strcpy(manufacturer, "Manufacturer");
    return 1;
}

test.py

from ctypes import *

MAX_STR = 256  # docs better say how big the buffers are required to be.

# int get_camera_info(char * description, char * serial_number, char * manufacturer)

dll = CDLL('./test')
dll.get_camera_info.argtypes = c_char_p,c_char_p,c_char_p
dll.get_camera_info.restype = c_int

desc = create_string_buffer(MAX_STR)
sn = create_string_buffer(MAX_STR)
mfg = create_string_buffer(MAX_STR)

ret = dll.get_camera_info(desc,sn,mfg)
print(desc.value.decode(),sn.value.decode(),mfg.value.decode())

输出:

Description 12345678 Manufacturer

注意.value returns 缓冲区开头的一个字节串,直到第一个空字节独占。 .raw 将转储包含缓冲区每个字节的字节字符串。 .decode() 使用 UTF-8 作为默认编码将字节字符串转换为 Unicode 字符串。