简体   繁体   English

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

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

I have a C/C++ dll with a function:我有一个 C/C++ dll 和一个 function:

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

This function takes the arguments and modifies them, so that you could print them.此 function 采用 arguments 并对其进行修改,以便您可以打印它们。 I'm trying to use this DLL from Python by using ctypes .我正在尝试通过使用ctypes从 Python 使用这个 DLL 。 I guess I would need to use ctypes.create_string_buffer to create an empty buffer so that I have a mutable object.我想我需要使用ctypes.create_string_buffer创建一个空缓冲区,以便我有一个可变的 object。 But then, how do I do so that I can pass it as an argument and then retrieve the data?但是,我该怎么做才能将它作为参数传递,然后检索数据?

Do I need to use cast(buffer_object, c_char_p_object) ?我需要使用cast(buffer_object, c_char_p_object)吗? How would this be any different from creating and passing a c_char_p object in the first place?这与首先创建和传递c_char_p object 有何不同? I don't know much about C/C++, but maybe I should be using ctypes.POINTER .我对 C/C++ 了解不多,但也许我应该使用ctypes.POINTER

My problem was that after passing a c_char_p type object as an argument I'm getting the error: OSError: exception: access violation reading 0x00000000 .我的问题是,在传递c_char_p类型 object 作为参数后,我收到错误: OSError: exception: access violation reading 0x00000000

If you need any help trying to understand what my question is, just ask.如果您需要任何帮助来理解我的问题,请提出。 Or if you think I'm better off using something like cppyy, then I would need help with that too.或者,如果您认为我最好使用 cppyy 之类的东西,那么我也需要帮助。 :)

Here's the basics.这是基础知识。 Although not strictly required in this case, setting .argtypes and .restype correctly helps ctypes marshal parameters correctly and detect incorrectly passed parameters.尽管在这种情况下没有严格要求,但正确设置.argtypes.restype有助于ctypes正确编组参数并检测错误传递的参数。

Similar to passing arrays to C functions, create_string_buffer returns an c_char_Array_array_ size object, but it is marshaled as a pointer to it's first element ( c_char_p ) so it agrees with the .argtypes assignment. Similar to passing arrays to C functions, create_string_buffer returns an c_char_Array_array_ size object, but it is marshaled as a pointer to it's first element ( c_char_p ) so it agrees with the .argtypes assignment.

Without the .argtypes assignment, passing something incorrect such as an int or a create_unicode_buffer() array would crash or have the wrong result.如果没有.argtypes赋值,传递不正确的东西,例如intcreate_unicode_buffer()数组会崩溃或产生错误的结果。 But defining it correctly would catch those errors and raise an exception.但是正确定义它会捕获这些错误并引发异常。

test.c测试.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测试.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())

Output: Output:

Description 12345678 Manufacturer

Note that .value returns a byte string at the beginning of the buffer up to the first null byte exclusive.请注意, .value在缓冲区的开头返回一个字节字符串,直到第一个 null 字节除外。 .raw will dump a byte string with every byte of the buffer. .raw将与缓冲区的每个字节一起转储一个字节字符串。 .decode() converts a byte string into a Unicode string using UTF-8 as the default encoding. .decode()使用 UTF-8 作为默认编码将字节字符串转换为 Unicode 字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM