Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python ctype help: working with C unsigned char pointers

My first post so please take at easy. :) I'm a bit new to Python as well, but I like what I see so far. What I'm trying to do is access a c library that allows me to print to a receipt printer via Python. I'm creating a wrapper in Python using ctypes, and everything is going great, EXCEPT for two functions. Here our their prototypes:

int C56_api_printer_write(int printer, unsigned char * data, int size, unsigned long timeout_ms);
int C56_api_printer_read(int printer, unsigned char * data, int size, unsigned long timeout_ms);

My issue is with writing to and reading from unsigned char pointers using ctypes. I have to read in a bitmap file in Python and pass the array to the write function, or in the case of read, I need to read that pointer in as an integer array.

I've been floundering on this one for the past few hours, so I was hoping an expert could help by posting a simple example of how this could be accomplished.

Thank you!

like image 768
CharlieY Avatar asked Mar 02 '12 17:03

CharlieY


People also ask

What is Ctype in Python?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

Does ctypes work with C++?

ctypes is the de facto standard library for interfacing with C/C++ from CPython, and it provides not only full access to the native C interface of most major operating systems (e.g., kernel32 on Windows, or libc on *nix), but also provides support for loading and interfacing with dynamic libraries, such as DLLs or ...

What is Restype?

Specifies the type of AFP print resources ACIF retrieves from the resource directories or libraries for inclusion in the resource file (specified with the RESOBJDD parameter).


2 Answers

Ok, after help from Kyss I was able to finish this out. Here's my test code and result for completion to this problem:

My test.c code:

#include <stdio.h>
int test(unsigned char *test, int size){
    int i;
    for(i=0;i<size;i++){
        printf("item %d in test = %d\n",i, test[i]);
    }   
}
int testout(unsigned char *test, int *size){
   test[2]=237;
   test[3]=12;
   test[4]=222;
   *size = 5;
}
main () {
    test("hello", 5); 
    unsigned char hello[] = "hi";
    int size=0;
    int i;
    testout(hello,&size);
    for(i=0;i<size;i++){
        printf("item %d in hello = %d\n",i, hello[i]);
    }   
}

I created a main for testing my c function. Here's the output of the function test:

item 0 in test = 104
item 1 in test = 101
item 2 in test = 108
item 3 in test = 108
item 4 in test = 111
item 0 in hello = 104
item 1 in hello = 105
item 2 in hello = 237
item 3 in hello = 12
item 4 in hello = 222

Then I compiled for shared, so it could be used from python:

gcc -shared -o test.so test.c

And here's what I used for my python code:

from ctypes import *

lib = "test.so"
dll = cdll.LoadLibrary(lib)
testfunc = dll.test
print "Testing pointer input"
size = c_int(5)
param1 = (c_byte * 5)()
param1[3] = 235 
dll.test(param1, size)
print "Testing pointer output"
dll.testout.argtypes = [POINTER(c_ubyte), POINTER(c_int)]
sizeout = c_int(0)
mem = (c_ubyte * 20)() 
dll.testout(mem, byref(sizeout))
print "Sizeout = " + str(sizeout.value)
for i in range(0,sizeout.value):
    print "Item " + str(i) + " = " + str(mem[i])

And the output:

Testing pointer input
item 0 in test = 0
item 1 in test = 0
item 2 in test = 0
item 3 in test = 235
item 4 in test = 0
Testing pointer output
Sizeout = 5
Item 0 = 0
Item 1 = 0
Item 2 = 237
Item 3 = 12
Item 4 = 222

Works!

My only issue now resides with dynamic resizing of the c_ubyte array based on the size of the output. I have posted a separate question regarding that though.

Thanks for your help Kyss!

like image 118
CharlieY Avatar answered Oct 17 '22 00:10

CharlieY


Does the following help you? Please let me know if it gives you errors or I misunderstood your question:

size =
printer =
timeout =

data = (ctypes.c_ubyte * size)() # line 5

C56_api_printer_read(printer, data, size, timeout)

# manipulate data eg
data[3] = 7

C56_api_printer_write(printer, data, size, timeout)

Edit:

About line 5: See also http://docs.python.org/library/ctypes.html sections 15.17.1.13 and 15.17.1.20.

(ctypes.c_ubyte * size)

gives a function that constructs a ctypes array of length size. Then in this line I call the function with no arguments, causing initialization with zeros.

like image 44
Kyss Tao Avatar answered Oct 17 '22 00:10

Kyss Tao