[英]convert mmap to ctypes void ** in python (swig)
我已经使用 swig 在 C 中生成了一个库的包装器。
我需要在 python 中复制 C 中的代码,但我不知道如何将 go 从 mmap 复制到 void **
在 C 中:
char *image_buf;
...
axidma_fd = open("/dev/axidma", O_RDWR|O_EXCL);
...
image_buf = mmap(NULL, image_byte_size, PROT_READ|PROT_WRITE,
MAP_SHARED, axidma_fd, 0);
...
trans.num_frame_buffers = 1;
trans.frame_buffers = (void **)&image_buf;
在 python
axidma_fd = os.open("/dev/axidma", os.O_RDWR|os.O_EXCL)
...
image_buf_1 = mmap.mmap(vdma_fd,188, mmap.MAP_SHARED,mmap.ACCESS_WRITE| mmap.ACCESS_READ);
...
# Convert mmap to c_char
char_pointer = c_char.from_buffer(image_buf_1) ???? (but type is c_char not pointer)
# Double void
trans.frame_buffers = ??
如何将 mmap 转换为指针?
如何获得双指针?
直接在 python 中执行此操作或通过实例化 libc 库会更有效吗? 例如像这样
libc = ctypes.CDLL("libc.so.6")
image_mmap = ctypes.c_void_p(libc.mmap(0,188,mmap.ACCESS_WRITE| mmap.ACCESS_READ,mmap.MAP_SHARED,vdma_fd)
太感谢了
已编辑 1它对我的解释有点糟糕
如果我做:
image_buf_1 = mmap.mmap(vdma_fd,188, mmap.MAP_SHARED,mmap.ACCESS_WRITE| mmap.ACCESS_READ)
image_map = c_void_p.from_buffer(image_buf_1)
image_map 是无
>>> image_map
c_void_p(None)
另一方面,如果我这样做
libc = ctypes.CDLL("libc.so.6")
image_mmap = ctypes.c_void_p(libc.mmap(0,188,mmap.ACCESS_WRITE| mmap.ACCESS_READ,mmap.MAP_SHARED,vdma_fd))
image_mmap 是一个有效的指针。
>>> image_mmap
c_void_p(18446744073709551615)
但是当试图将它分配给
trans.frame_buffers = image_mmap
报告:
trans.frame_buffers=image_mmap
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: in method 'axidma_video_transaction_frame_buffers_set', argument 2 of type 'void **'
我需要将 mmap 转换为 void **
清单[Python.Docs]:mmap - 内存映射文件支持。
检查 [SO]:C function 通过 ctypes 从Python调用时返回不正确的值(@CristiFati 的答案) 。
Working with double (or multiple) pointers (that store array like data - like images are) is a bit tricky in CTypes (as seen in [SO]: C++ & Python: Pass and return a 2D double pointer array from python to c++ ( @CristiFati 的回答) )。
下面是一个使用 arrays 的示例。
代码00.py :
#!/usr/bin/env python
import ctypes as ct
import mmap
import os
import sys
#CharPtrPtr = ct.POINTER(ct.POINTER(ct.c_char))
def main(*argv):
h = 3
w = 4
fname = "file.txt"
with open(fname, mode="wb") as f:
f.write(b"\x00" * h * w)
fd = os.open(fname, os.O_RDWR | os.O_CREAT)
buf = mmap.mmap(fd, h * w, mmap.MAP_SHARED, mmap.ACCESS_WRITE | mmap.ACCESS_READ)
CharArrArr = ct.c_char * w * h
img = CharArrArr.from_buffer(buf)
for i in range(h):
for j in range(w):
img[i][j] = 0x41 + 2 * i * w + j
del img
buf.close()
os.close(fd)
with open(fname) as f:
print("File contents:", f.read())
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output :
(qaic-env) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q073614606]> python./code00.py Python 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0] 064bit on linux File contents: ABCDIJKLQRST Done.
看着编辑,似乎我没有做对。 为什么需要void**指针? 你在用它做什么(什么是trans )? 请分享代码,而不仅仅是零散的片段。
如果我做对了,您需要获取mmap的返回值(作为void* ),并进一步传递其地址(这是一个void** )。 您可以这样做(使用代码中的片段):
image_buf_1 = mmap.mmap(vdma_fd, 188, mmap.MAP_SHARED, mmap.ACCESS_WRITE | mmap.ACCESS_READ)
image_map = ctypes.c_void_p.from_buffer(image_buf_1)
trans.frame_buffers = ctypes.byref(image_mmap) # or ctypes.pointer(image_mmap)
另一个问题( NULL指针):您将fd 0 (即StdIn )传递给libc.mmap (还要检查第二个 URL是否有隐藏的错误),而对于mmap.mmap您使用的是“真实”描述符,所以我假设该描述符 memory 无法正确映射(您应该检查两种情况下的mmap结果( image_buf_1 ))。
部分感谢这个答案: ctypes reference double pointer
尝试ctypes.byref()
。 示例代码:
import ctypes
import mmap
import os
FILENAME=#<your filename>
FILELENGTH=#<your file's length>
fd = os.open(FILENAME, os.O_RDWR|os.O_EXCL)
image_buf_1 = mmap.mmap(fd, FILELENGTH, mmap.MAP_SHARED|mmap.ACCESS_WRITE|mmap.ACCESS_READ)
image_map = ctypes.c_void_p.from_buffer(image_buf_1)
print(f"{image_map.value:x}")
print(f"{ctypes.byref(image_map)}") # this is the pointer you're looking for
os.system(f'cat /proc/$PPID/maps | grep {FILENAME}') # verify the pointer value
os.close(fd)
对不起,我不知道你所说的“双指针”是什么意思; mmap 返回一个 void*,这里用 ctypes.byref(image_map) 表示。
至于更有效的方法,您当然可以进行分析,但通常您的投资来自执行 I/O 而不是设置 I/O(我假设 ctypes.DLL 是通过 dlopen() 实现的,它非常轻量级对于已经加载的库)。 除非您打开大量文件,否则我猜您想根据是否要使用 Python 中的数据(您可能需要 Python mmap 对象)来选择您的方法。
--note:我简单地尝试了您引用的 libc 方法,但 mmap 返回 -1,无效参数。 我没有调查我在那里做错了什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.