如何在Python中从指针地址读取数据?

7

我想在Python脚本中从特定地址开始读取一定数量的字节。例如,我想要从0x561124456开始读取40000个字节。

指针是由C#应用程序提供的。我想使用此方法在应用程序和脚本之间传递数据。我之前通过本地主机上的TCP套接字进行了尝试,但我也想尝试这种方法。

我该如何做到这一点?


1
你为什么想要这样做?Python 没有指针。是什么负责将那些字节放在那个地址上呢? - Daniel Roseman
@DanielRoseman 我已经更新了问题。 - Cristian M
我在想ctypes.<some c type>.from_address在这里是否有用?我刚试了两次,都出现了OverflowError和硬崩溃,没有任何异常,但也许有什么方法可以避免这些问题。 - Kevin
嗯,将数据放入内存位置不是在应用程序之间传递信息的好办法。这就是套接字存在的目的。 - Daniel Roseman
@DanielRoseman 为什么这不是一个好方法?我可以将缓冲区固定,这样它就不会被释放,并将指针传递给脚本。我认为这种方法比使用通过本地主机的套接字更快,因为后者的性能受到 CPU 和 TCP/IP 堆栈性能的限制。 - Cristian M
3个回答

10
如果您真的想要,就尽情享受吧:
import ctypes
g = (ctypes.c_char*40000).from_address(0x561124456)

看起来是段错误的问题。两种语言都有良好的套接字连接库(套接字、RPC等),所以如果这是一个大项目,我认为你应该重新考虑一下。


4

当我从C语言得到一个内存地址指针时,我发现在Python中使用"list(listSize * listDataType).from_address(memoryPointer)"可以创建C内存的内部副本。如果内存中的数据很大,Python使用内部副本创建列表对象将需要很长时间。为了避免内部拷贝,我在Python中使用了ctypelib.as_array:

import ctypes
import binascii
import numpy as np

myCfunslib.getData.restype = ctypes.c_void_p
#myCfunslib.getData.restype=ctypes.POINTER(ctypes.c_ubyte)#no need to cast
dataSize = 1092 * 1208
#call the c function to get the data memory pointer
cMemoryPointer = myCfunslib.getData();
newpnt = ctypes.cast(cMemoryPointer, ctypes.POINTER(ctypes.c_ubyte))
# and construct an array using this data
DataBytes = np.ctypeslib.as_array(newpnt, (dataSize,)) #no internal copy
print "the mid byte of the data in python side is ", DataBytes[dataSize/2]

工作得很好。希望找到一种不需要引入所有numpy的方法。我试图窥探一下numpy内部的实现方式,但有些困难。 - lazieburd

1

我碰巧遇到了类似的问题。我的Python脚本加载.so库以从C++ .so获取图像缓冲区地址。在获取缓冲区地址后,我需要能够读取缓冲区中的每个字节。我使用了"from_address"来创建一个列表对象:

imageBytes = list(c_ubyte * dataSize).from_address(pointer)

以下内容展示了如何从C++传递内存地址到Python以及如何在Python端访问内存数据。在C++代码frameprovider.cpp中:
dataPackPtr = new DataPack(); 

DataPack * getFrame(){
    uint32_t width = 1920;
    uint32_t height = 1208;
    const size_t buffersize = width * height * 4;//rgba, each color is one byte
    unsigned char* rgbaImage = (unsigned char * )malloc(buffersize);
    memset(rgbaImage, 0, buffersize); // set all the buffer data to 0.
    dataPackPtr->width = width;
    dataPackPtr->height = height;
    dataPackPtr->buffersize = buffersize;
    dataPackPtr->bufferPtr = rgbaImage;
    return dataPackPtr;
}

extern "C" {
    DataPack* getFrame_wrapper(){
        return getFrame();
    }
}

我的Python:
import ctypes
import binascii
lib = ctypes.cdll.LoadLibrary('/libpath/frameprovider.so')
print vars(lib)

class dataPack(ctypes.Structure):
    _fields_ = [("width",ctypes.c_int),
                ("height",ctypes.c_int),
                ("buffersize",ctypes.c_int),
                ("bufferAddress", ctypes.c_void_p)]

lib.getFrame_wrapper.restype = ctypes.POINTER(dataPack)
data = lib.getFrame_wrapper()
print "in python the w= ", data.contents.width, "h=",data.contents.height
print "the buffersize=",data.contents.height
imageBytes = list(
(data.contents.buffersize * ctypes.c_ubyte).
 from_address(data.contents.bufferAddress))        

print "the len of imageBytes are ", len(imageBytes)
print imageBytes[data.contents.buffersize -1] #print the last byte in the buffer
print "in python, the hex value of element 12 is ", hex(imageBytes[12])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接