Python 如何将bytearray的一部分复制到c_void_p引用内存,反之亦然?

Python 如何将bytearray的一部分复制到c_void_p引用内存,反之亦然?,python,ctypes,Python,Ctypes,在Python应用程序中,我有一个包含一些数据的bytearray。我的python代码由一些外部本机库(DLL/so/dylib)调用(使用ctypes和its)。其中一个回调函数包含指向在该外部库中分配的非托管缓冲区的指针 我需要将bytearray的一部分复制到此非托管缓冲区中,或者将非托管缓冲区的内容复制到特定位置的bytearray中 简单地说,我有 def copy_from_python_callback(c_void_p_parameter : c_void_p, offset

在Python应用程序中,我有一个包含一些数据的bytearray。我的python代码由一些外部本机库(DLL/so/dylib)调用(使用ctypes和its)。其中一个回调函数包含指向在该外部库中分配的非托管缓冲区的指针

我需要将bytearray的一部分复制到此非托管缓冲区中,或者将非托管缓冲区的内容复制到特定位置的bytearray中

简单地说,我有

def copy_from_python_callback(c_void_p_parameter : c_void_p, offset : int, size : int):
  managed_buf = bytearray(some_size) # suppose we have data in this buffer already
  unmanaged_buf = c_void_p_parameter
  # what do I need to do here?
  # src_buf = pointer_to_specific_byte_in_managed_buf
  memmove(unmanaged_buf, src_buf, size)

def copy_to_python_callback(c_void_p_parameter : c_void_p, offset : int, size : int):
  managed_buf = bytearray(some_size) #some_size is assumed to be larger than offset + size
  unmanaged_buf = c_void_p_parameter
  # what do I need to do here?
  # dst_buf = pointer_to_specific_byte_in_managed_buf
  memmove(dst_buf, unmanaged_buf, size)

在其他语言中,答案很简单——我要么调用专用方法(例如.NETFramework的MsHall类),要么获取指向BytErar中特定字节(用C++或Pascal等本地语言)的指针。不幸的是,如果没有中间字节()或类似的缓冲区,我看不到如何在Python中执行这些操作

我有一些使用intermediate bytes()实例的方法,但是仅仅因为无法获取指针而复制数据对我来说似乎很奇怪

我正在寻找独立于版本的解决方案,如果可能的话,但也只能使用python3。先谢谢你

列表

你要找的是可能的。数组(CTypes)很方便
下面是一个“小”示例。出于演示目的,缓冲区仅包含“人性友好”字符

dll00.c:

#包括
#包括
#包括
#如果已定义(_WIN32)
#定义DLL00_导出_API__declspec(dllexport)
#否则
#定义DLL00\u导出\u API
#恩迪夫
#定义C_标签“来自C-”
typedef int(*ReadFunc)(void*ptr,uint32\u t偏移量,uint32\u t大小);
typedef int(*WriteFunc)(void*ptr,uint32\u t偏移量,uint32\u t大小);
#如果已定义(uuu cplusplus)
外部“C”{
#恩迪夫
DLL00_导出_API int testBufferCallbacks(uint32_t bufSize,
ReadFunc read、uint32\u t readOffset、uint32\u t readSize、,
WriteFunc write、uint32\u t writeOffset、uint32\u t writeSize);
#如果已定义(uuu cplusplus)
}
#恩迪夫
无效主缓冲区(结构尺寸为8*buf,尺寸为32){
printf(“%sBuffer(大小%d)0x%016llX\n内容:”,C_标记,大小,(uint64_t)buf);
对于(uint32_t i=0;i0)){
printf(“\n%scaling read(0x%016llX,%u,%u)…\n”,C_标记,(uint64_t)buf,readOffset,readSize);
读取(buf、读取偏移量、读取大小);
}
如果((write!=NULL)&&(writeSize>0)){
printf(“\n%scaling write(0x%016llX,%u,%u)…\n”,C_标记,(uint64_t)buf,writeOffset,writeSize);
写入(buf、写入偏移、写入大小);
普林布弗(cBuf,bufSize);
}
如果((读取!=NULL)&&(读取大小>0)){
printf(“\n%scaling read(0x%016llX,%u,%u)…\n”,C_标记,(uint64_t)buf,readOffset,readSize);
读取(buf、读取偏移量、读取大小);
}
普林布弗(cBuf,bufSize);
免费(buf);
printf(“\n%sDone.\n”,C_标记);
返回0;
}
代码00.py:

#/usr/bin/env蟒蛇3
导入系统
将ctypes导入为ct
DLL_NAME=“./dll00.DLL”
ReadFunc=ct.CFUNCTYPE(ct.c_int,ct.c_void_p,ct.c_uint32,ct.c_uint32)
WriteFunc=ct.CFUNCTYPE(ct.c_int,ct.c_void_p,ct.c_uint32,ct.c_uint32)
def create_bytearray(大小、偏移量_字符=0x61):
contents=“”.连接(范围内i的chr(i)(偏移量字符,偏移量字符+大小))
返回bytearray(contents.encode())
def read_c_buf(buf:ct.c_void_p,偏移量:ct.c_uint32,尺寸:ct.c_uint32):
打印(“C buf:0x{0:016X}”。格式(buf))
ba=创建字节数组(0x1A)
打印(“Python初始缓冲区:{0:}”。格式(ba))
UCharArr=ct.c_uint8*尺寸
uchar_arr=UCharArr.from_缓冲区(ba,偏移量)#共享内存
ct.memmove(uchar_arr,buf,尺寸)
打印(“Python最终缓冲区:{0:}\n.”格式(ba))
返回0
def write__buf(buf:ct.c_void_p,偏移量:ct.c_uint32,大小:ct.c_uint32):
打印(“C buf:0x{0:016X}”。格式(buf))
ba=创建字节数组(大小+偏移量,偏移量字符=0x30-偏移量)
打印(“Python缓冲区:{0:}\n.”格式(ba))
UCharArr=ct.c_uint8*尺寸
uchar_arr=UCharArr.from_缓冲区(ba,偏移量)#共享内存
ct.memmove(buf,uchar_arr,尺寸)
返回0
def主(*argv):
dll00=ct.CDLL(DLL\u名称)
testBufferCallbacks=dll00.testBufferCallbacks
testBufferCallbacks.argtypes=(ct.c_uint32、ReadFunc、ct.c_uint32、ct.c_uint32、WriteFunc、ct.c_uint32、ct.c_uint32)
testBufferCallbacks.restype=ct.c_int
read_callback=ReadFunc(read_c_buf)
buf_尺寸=0x1A
读取偏移量=10
读取大小=16
write_callback=WriteFunc(write_c_buf)
写入偏移量=5
写入大小=10
res=testBufferCallbacks(buf_大小、读取_回调、读取_偏移量、读取_大小、写入_回调、写入_偏移量、写入_大小)
打印(“\n{0:s}返回:{1:d}”。格式(testBufferCallbacks.\uuuu name\uuuu,res))
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.join(sys.version.split(“\n”)中的项的item.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform))
main(*sys.argv[1:])
打印(“\n完成”)
输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q059255471]>sopr.bat
***设置较短的提示,以便粘贴到StackOverflow(或其他)页面时更适合***
[提示]>“c:\Install\x86\Microsoft\visualstudio Community\2017\VC\Auxiliary\Build\vcvarsall.bat”x64
**********************************************************************
**Visual Studio 2017开发公司