简体   繁体   中英

Is it possible to write data from void_pointer to file in python ctypes

I have a C-Program that acquires an image from my camera and writes the binary data to file.

I'm (thus far unsuccessfully) attempting to write a python script to mimic the C-code.

The Python ctypes example appears to execute without error UNTIL I try to write it to file. In other words, in Python the fwrite is unable to write the data to file in this instance. fwrite returns a value of 0 , indicating that 0 files were written.

So, I am asking the following: Since I have an external c-function that is reading out binary data, presumably to some buffer in memory, is it possible that the instance of Python ctypes simply does not have read access to this memory location? And if that is the case, is it possible for python ctypes to gain the permission necessary to access the appropriate area in memory?

For reference, I have included a (working as expected) simplified C example followed by the Python ctypes example below, which opens and creates the appropriate file but does not write to it.

//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 );
    }

}

And here is my Python version:

""" 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)

Create an array to use with a regular Python file. For example:

Get a void pointer:

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))

Now use it as an array:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM