【问题标题】:How can I read back from a buffer using ctypes?如何使用 ctypes 从缓冲区读回?
【发布时间】:2021-11-21 03:39:28
【问题描述】:

我有一个第三方库,我需要从中使用 python 脚本中的一个函数。这里是:

ReadFromBlob(PVOID blob, INT blob_size, PCSTR section, PCSTR key, const void **buffer, UINT * size)
  • blob - 一些指针?要读取的字节数
  • blob_size - blob 大小(以字节为单位)
  • 部分和键 - 字符串值,如“Image”
  • 缓冲区 - 要读取的字节数
  • 大小 - 缓冲区大小

文档给出了如何使用它的示例:

UINT size = 0;
PVOID buffer = NULL;
ReadFromBlob(<blob>, <blob_size>, "MainImage", "Image", &buffer, &size);

我不熟悉 C,所以参数类型让我很困惑。我需要能够从 python 的缓冲区中读取值。 这是我目前所拥有的:

from ctypes import *
lib = cdll.LoadLibrary(path_to_lib)
with open(filepath, 'rb') as file:
    data = file.read()
blob_size = c_int(len(data))
blob = cast(c_char_p(data), POINTER(c_char * blob_size.value))
b = bytes()
size = c_uint(len(b))
buffer = cast(cast(b, c_void_p), POINTER(c_char * size.value))
lib.ReadFromBlob(blob, blob_size, b"MainImage", b"Image", buffer, pointer(size))

但最后我仍然得到一个空缓冲区。请帮帮我。

【问题讨论】:

  • 你有函数官方文档吗?因为当前版本有点差。

标签: python c dll ctypes


【解决方案1】:

看起来该函数根据部分和键在 blob 中搜索数据,并返回指向 blob 数据的指针和大小,所以我创建了一个测试函数,它只是回显 blob 和大小作为输出参数:

#include <windows.h>
#include <stdio.h>

__declspec(dllexport)
void ReadFromBlob(PVOID blob, INT blob_size, PCSTR section, PCSTR key, const void **buffer, UINT * size) {
    printf("section=\"%s\" key=\"%s\"\n",section,key);
    *buffer = blob;            // just echo back input data for example
    *size = (UINT)blob_size;
}

这些类型看起来像 Windows 类型,ctypes 有一个子模块 wintypes,其中包含有助于获得正确类型的 Windows 定义。确保使用 Windows 类型的并行 ctypes 类型正确设置 .argtypes.restype。这有助于ctypes 检查参数是否正确传递。

import ctypes as ct
from ctypes import wintypes as w

dll = ct.CDLL('./test')

# Note the parallels between C types and ctypes types.
# PVOID is just "pointer to void" and LPVOID mean the same thing, etc.
dll.ReadFromBlob.argtypes = w.LPVOID,w.INT,w.LPCSTR,w.LPCSTR,ct.POINTER(w.LPCVOID),w.LPUINT
dll.ReadFromBlob.restype = None

# storage for returned values, passed by reference as output parameters
buffer = w.LPCVOID()
size = w.UINT()
dll.ReadFromBlob(b'filedata',8,b'Section',b'Key',ct.byref(buffer),ct.byref(size))
print(ct.cast(buffer,ct.c_char_p).value,size.value)

输出显示接收到的部分和键,并打印返回的 blob 数据和大小:

section="Section" key="Key"
b'filedata' 8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多