Pergunta

I've been trying to get an imgdata string of hexadecimal (unicode latin-1) values passed from Python via a pointer to imgdata to a function in C that I wrote. The C function will convert these hexadecimal source values which are Blue Green Red and Alpha to greyscale and then return the converted imgdata to the dst pointer address.

Currently the source values that C function prints out are not correct and much different than the hexadecimal values in imgdata. Any suggestions on what I am doing wrong when passing imgdata in Python to my C function? Is my ctypes datatype wrong?

Output from c function: src values: 120 src values: 212 src values: 201 src values: 1 src values: 0 src values: 0 src values: 0 src values: 0 src values: 0 src values: 0 src values: 0 src values: 0

Values should be: 4,8,20,0,1,7,12,0,6,7,14,0

Python code:

#imgdata format is BGRA
imgdata = '\x04\x08\x14\x00\x01\x07\x0c\x00\x06\x07\x0e\x00'
testlib = ctypes.CDLL('path/to/my/lib/testlib.so')
source = (c_char_p * 12) (imgdata) 
destination = (c_uint8 * 12)()
testlib.grey.argtypes = (ctypes.c_void_p, ctypes.c_void_p,ctypes.c_int)
src = pointer(source)
dst = pointer(destination)
testlib.grey(dst,src,3)
p = ctypes.string_at(dst,12)
byte_array = map(ord, p)

C code:

#include <stdio.h>
#include <stdint.h>

void grey(uint8_t *dst, uint8_t *sc, int num_pixels) {
    int k;
    for (k=0; k<12; k++)
    {
      printf("src values: %d ", *sc++);
    }
    // additional BGRA to Greyscale conversion code not shown
Foi útil?

Solução

Python isn't that hard you want it to be. This would look sort of:

    imgdata = '\x04\x08\x14\x00\x01\x07\x0c\x00\x06\x07\x0e\x00'
    testlib = ctypes.CDLL('path/to/my/lib/testlib.so')
    dest = (c_uint8 * 12)()
    testlib.grey(dest, imgdata, 12)
    byte_array = bytearray(dest) # if you really neeed it

Edit: read voted up eryksun's comments (irrelevant since he deleted them). He explains how to make it right with your approach.

Oh, well, he insisted, so here's his code:

    imgdata = '\x04\x08\x14\x00\x01\x07\x0c\x00\x06\x07\x0e\x00'
    testlib = ctypes.CDLL('path/to/my/lib/testlib.so')
    dest = (ctypes.c_char * len(imgdata))()
    testlib.grey.restype = None
    testlib.grey.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int]
    testlib.grey(dest, imgdata, len(dest))
    byte_array = bytearray(dest) # or just use dest.raw which is a python str

and his explanation:

c_char_p is a char* and an array of 12 char pointers is incorrect, and passing a pointer to that is doubly incorrect, and the only reason it didn't die in a ArgumentError is that c_void_p in argtypes accepts a lot without complaining -- Python integers and strings, and ctypes pointers and arrays.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top