我正在开发一个使用 C 库 libupnp 的 Python 应用程序。我正在使用 CTypes 来使用足够简单的库。我遇到的问题是当我为读取请求注册回调函数时。该函数具有以下形式的原型(prototype):
int read_callback(void *pFileHandle, char *pBuf, long nBufLength);
pFileHandle 只是一些文件句柄类型。 pBuf 是一个可写内存缓冲区。这是数据输出的地方。 nBufLength 是要从文件中读取的字节数。返回一个状态码。
我有一个 Python 函数指针。这很容易实现,但是当我定义一个 Python 函数来处理这个回调时,我发现 pBuf 没有被写入,因为 Python 字符串是不可变的,当你分配或修改它们时,它们会创建新的实例。这带来了一个大问题,因为 C 库期望在函数完成请求的文件数据时返回 char 指针。由于 Python 字符串的方式,每次缓冲区最终都是空的。有没有办法在不修改 C 库的情况下解决这个问题?
处理程序应该修改给定的缓冲区参数,这是我的问题。
所以我想要发生的是调用 Python 函数来执行某个文件的读取(可能在内存中、文件系统句柄中或介于两者之间的任何文件中)。 pBuf 参数由流的读取填充(同样在 Python 中)。然后回调返回到已写入 pBuf 的 C 代码。
最佳答案
回调是用 pBuf 和 nBufLength 调用的。 pBuf 已经分配了可写内存,但如果您请求 pBuf.value,它会被转换为不可变的 python 字符串。
而是将 pBuf 转换为可以直接修改的对象:
## If pBuf is c_char_p, then convert to writable object
c = ctypes.cast(pBuf, ctypes.POINTER(ctypes.c_char))
## At this point, you can set individual bytes
## with c[i] = x, but this is dangerous and there's a safer way:
## get address of string
addr = ctypes.addressof(c.contents)
## convert to char[] for safe writing
c2 = (c_char*nBufLength).from_address(addr)
## see how many bytes to write
nb = min(len(msg), nBufLength-1)
c2[:nb] = msg[:nb]
c2[nb+1] = '\0'
关于Python ctypes : How to modify an existing char* array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14310310/