[英]How to access the value of a ctypes.LP_c_char pointer?
I have defined a struct :我定义了一个结构:
class FILE_HANDLE(Structure):
_fields_ = [
("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", POINTER(c_char))
]
The struct is initialised :结构被初始化:
buf = create_string_buffer(f_handle.handle_bytes)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
I am passing it by reference to a function that populates it.我通过引用填充它的函数来传递它。
ret = libc.name_to_handle_at(dirfd, pathname, byref(fh), byref(mount_id), flags)
I can check with strace that the call works, but I have not been able to figure out how to access the value of fh.f_handle我可以使用 strace 检查该调用是否有效,但我无法弄清楚如何访问 fh.f_handle 的值
fh.f_handle type is <ctypes.LP_c_char object at 0x7f1a7ca17560>
fh.f_handle 类型是<ctypes.LP_c_char object at 0x7f1a7ca17560>
fh.f_handle.contents type is <ctypes.LP_c_char object at 0x7f1a7ca17560>
but I get a SIGSEGV if I try to access its value. fh.f_handle.contents 类型是<ctypes.LP_c_char object at 0x7f1a7ca17560>
但如果我尝试访问它的值,我会得到一个 SIGSEGV。
How could I get 8 bytes from f_handle into a string or array ?如何从 f_handle 获取 8 个字节到字符串或数组中?
Everything actually looks right for what you've shown, but without seeing the explicit C definition of the structure and function you are calling it is difficult to see the problem.一切实际上看起来都适合您所展示的内容,但是如果没有看到您正在调用的结构和函数的显式 C 定义,就很难看出问题所在。
Here's an example that works with what you have shown.这是一个适用于您所展示内容的示例。 I inferred what the C definitions should be from what you have declared in Python, but most likely your definition is different if you get a segfault.我从您在 Python 中声明的内容推断出 C 定义应该是什么,但是如果您遇到段错误,您的定义很可能会有所不同。
struct FILE_HANDLE
{
unsigned int handle_bytes;
int handle_type;
char* f_handle;
};
__declspec(dllexport) int name_to_handle_at(int dirfd, char* pathname, struct FILE_HANDLE* fh, int* mount_id, int flags)
{
unsigned int i;
printf("dirfd=%d pathname=%s fh->handle_bytes=%u fh->handle_type=%d flags=%d\n", dirfd, pathname, fh->handle_bytes, fh->handle_type, flags);
for(i = 0; i < fh->handle_bytes; ++i)
fh->f_handle[i] = 'A' + i;
*mount_id = 123;
return 1;
}
from __future__ import print_function
from ctypes import *
class FILE_HANDLE(Structure):
_fields_ = [("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", POINTER(c_char))]
buf = create_string_buffer(8);
fh = FILE_HANDLE(8,0,buf)
libc = CDLL('test.dll')
mount_id = c_int(0)
ret = libc.name_to_handle_at(1,b'abc',byref(fh),byref(mount_id),7)
print('mount_id =',mount_id.value)
print('fh.f_handle =',fh.f_handle[:fh.handle_bytes])
dirfd=1 pathname=abc fh->handle_bytes=8 fh->handle_type=0 flags=7
mount_id = 123
fh.f_handle = b'ABCDEFGH'
Note that since the structure is declared as a pointer to a single character, printing fh.f_handle.contents
would only print b'A'
.请注意,由于该结构被声明为指向单个字符的指针,因此打印fh.f_handle.contents
只会打印b'A'
。 Using slicing, I've instructed Python to index the pointer up to the length allocated.使用切片,我已经指示 Python 将指针索引到分配的长度。
If this doesn't work for you, provide a Minimal, Complete, and Verifiable example (as I have) to reproduce your error exactly.如果这对您不起作用,请提供一个最小、完整和可验证的示例(如我所见)以准确重现您的错误。
fh.f_handle is shown as LP_c_char because you defined the struct that way. fh.f_handle 显示为 LP_c_char 因为您以这种方式定义了结构。
buf = create_string_buffer(8)
print type(buf)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
print type(fh.f_handle)
Will output会输出
<class 'ctypes.c_char_Array_8'>
<class 'ctypes.LP_c_char'>
You have defined your struct to accept a pointer to a c_char.您已将结构定义为接受指向 c_char 的指针。 So when you try to access fh.f_handle it will expect the value to be a memory address containing the address to the actual single c_char.因此,当您尝试访问 fh.f_handle 时,它会期望该值是包含实际单个 c_char 的地址的内存地址。
But by trying to input a c_char * 8 from the string buffer it will convert the first part of your buffer to a pointer.但是通过尝试从字符串缓冲区输入 c_char * 8 ,它会将缓冲区的第一部分转换为指针。
Python tries to dereference your char[0] which means that it will look for a memory address with the value of the character you have defined in char[0]. Python 会尝试取消对您的 char[0] 的引用,这意味着它将使用您在 char[0] 中定义的字符的值来查找内存地址。 That memory address is not valid, so your interpreter will signal a SIGSEGV.该内存地址无效,因此您的解释器将发出 SIGSEGV 信号。
Now to create a class which properly handles a variable length buffer is quite difficult.现在创建一个正确处理可变长度缓冲区的类是相当困难的。 An easier option is to pass the buffer as an opaque handle, to access it afterwards you need to cast it back to a char array.一个更简单的选择是将缓冲区作为一个不透明的句柄传递,之后访问它你需要将它转换回一个字符数组。
Example:例子:
class FILE_HANDLE(Structure):
_fields_ = [
("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", c_void_p)
]
buf = create_string_buffer(8)
buf = cast(buf, c_void_p)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
f_handle_value = (c_char * fh.handle_bytes).from_address(fh.f_handle)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.