【问题标题】:Is it possible to write data from void_pointer to file in python ctypes是否可以将数据从 void_pointer 写入 python ctypes 中的文件
【发布时间】:2013-06-29 05:20:54
【问题描述】:

我有一个 C 程序,它从我的相机获取图像并将二进制数据写入文件。

我(迄今为止没有成功)尝试编写一个 python 脚本来模仿 C 代码。

Python ctypes 示例似乎执行没有错误,直到我尝试将其写入文件。换句话说,在 Python 中,fwrite 在这种情况下无法将数据写入文件。 fwrite 返回值0,表示写入了0 文件。

所以,我要问以下问题: 由于我有一个外部 c 函数正在读取二进制数据,大概是内存中的某个缓冲区,Python ctypes 的实例是否可能根本没有对该内存位置的读取访问权限?如果是这种情况,python ctypes 是否有可能获得访问内存中适当区域所需的权限?

作为参考,我包含了一个(按预期工作)简化的 C 示例,后面是下面的 Python ctypes 示例,它打开并创建了适当的文件,但不写入。

//Data Saving Sample
//The sample will open the first camera attached
//and acquire 3 frames.  The 3 frames will be saved
//in a raw format and can be opened with applications
//such as image-j

#define NUM_FRAMES  3
#define NO_TIMEOUT  -1

#include "stdio.h"
#include "picam.h"
#include <iostream>
using namespace std;

int main()
{

    // The following structure contains the image data
    AvailableData data;

    int readoutstride = 2097152;
    FILE *pFile;


    Acquire( NUM_FRAMES, NO_TIMEOUT, &data, &errors );

    pFile = fopen( "sampleX3.raw", "wb" );
    if( pFile )
    {
        fwrite( data.initial_readout, 1, (NUM_FRAMES*readoutstride), pFile );
        fclose( pFile );
    }

}

这是我的 Python 版本:

""" Load the picam.dll """
picamDll = 'DLLs/Picam.dll'
picam = ctypes.cdll.LoadLibrary(picamDll)

libc = ctypes.cdll.msvcrt
fopen = libc.fopen

data = AvailableData()
readoutstride = ctypes.c_int(2097152)

"""
This is the C-structure form from the provided header file, followed by the Python syntax for creating the same structure type
typedef struct AvailableData
{
    void* initial_readout;
    int64 readout_count;
} AvailableData;

class AvailableData(ctypes.Structure):
    _fields_ = [("initial_readout", ctypes.c_void_p), ("readout_count",ctypes.c_int64)]
"""

"""
Simplified C-Prototype for Acquire

Acquire(
int64                       readout_count,
int                       readout_time_out,
AvailableData*         available);
"""
picam.Acquire.argtypes = int64, int, ctypes.POINTER(AvailableData)

picam.Acquire.restype = int

print picam.Acquire( 3, -1, ctypes.byref(data), ctypes.byref(errors))

""" Write contents of Data to binary file """
fopen.argtypes = ctypes.c_char_p, ctypes.c_char_p
fopen.restype = ctypes.c_void_p

fwrite = libc.fwrite
fwrite.argtypes = ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p
fwrite.restype = ctypes.c_int

fclose = libc.fclose
fclose.argtypes = ctypes.c_void_p,
fclose.restype = ctypes.c_int

fp = fopen('PythonBinOutput.raw', 'wb')
print 'fwrite returns: ',fwrite(data.initial_readout, 3*readoutstride.value, 1, fp)
fclose(fp)

【问题讨论】:

  • 如果你去掉所有不相关的 Picam 东西会更好,这会让人们很难测试和调试你的代码。请参阅sscce.org,了解有关如何为问题提供好的示例代码的一些想法。
  • @abarnert 同意——刚刚做了一些清理工作,谢谢
  • 同时,readoutstride.value 到底是什么?确定不是 0?
  • @abarnert 是的,我可以调用一个函数来返回它应该是什么值,即2097152。为了简化,我省略了那部分代码。顺便说一句,这对应于 1024x1024x2 字节。摄像头为 16 位,尺寸为 1024x1024。
  • 编辑后的版本在没有 Picam 的情况下仍然无法运行。您应该能够在完全不使用它的情况下重现该问题。例如,只需使用 Python 创建一个具有 3*2097152 字节数据的c_char_p,然后将castit 转换为c_void_p。或者,也可以调用一个标准的 C 函数,它会为您提供 c_void_p 并在其中包含数据。如果您不能以这种方式重现问题,那么任何问题都必须在 Picam 代码中。如果您可以,其他人可以为您调试问题。

标签: python ctypes void-pointers memory-address


【解决方案1】:

创建一个用于常规 Python 文件的数组。例如:

获取一个空指针:

class AvailableData(Structure):
    _fields_ = [
        ("initial_readout", c_void_p), 
    ]

cglobals = CDLL(None) # POSIX dlopen
cglobals.malloc.restype = c_void_p

size = 100  # 3 * readoutstride.value
data = AvailableData(cglobals.malloc(size))

现在将其用作数组:

buf = (c_char * size).from_address(data.initial_readout)
with open('PythonBinOutput.raw', 'wb') as f: 
    f.write(buf)

【讨论】:

    猜你喜欢
    • 2014-01-27
    • 1970-01-01
    • 2020-07-28
    • 2020-07-13
    • 2021-04-23
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多