It's working! I don't understand the line rx_buf = (c_uint8 * rx_buf_size).from_buffer_copy(string_buf) or where .from_buffer_copy() came from but it works...
I promise I will not knowingly pass Python strings to C. Thanks. > -----Original Message----- > From: eryksun [mailto:eryk...@gmail.com] > Sent: Wednesday, October 22, 2014 4:16 AM > To: Wilson, Pete > Cc: tutor@python.org > Subject: Re: [Tutor] Passing Data to .DLL > > On Tue, Oct 21, 2014 at 7:04 PM, Wilson, Pete <pete.wil...@atmel.com> > wrote: > > > > ProcessIncomingSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), > > c_uint16) process_incoming_serial_data = > > pt_dll.ProcessIncomingSerialData > process_incoming_serial_data.argtypes > > = [ProcessIncomingSerialData_t] > > ProcessIncomingSerialData takes two parameters: uint8_t *rx_buf and > uint16_t size. > > process_incoming_serial_data.argtypes = [POINTER(c_uint8), > c_uint16] > process_incoming_serial_data.restype = None > > The buffer parameter isn't const, so pass a copy of string_buf. > > size = len(string_buf) > rx_buf = (c_uint8 * size).from_buffer_copy(string_buf) > process_incoming_serial_data(rx_buf, size) > > I'm going to meander off topic a bit to give you a warning... > > Python strings are immutable by contract, so don't pass them directly > to C functions that might modify them. String immutability makes > interning possible, sometimes just locally in the code object and > sometimes globally in the interpreter. Here's an example of both in > CPython 2.7: > > import abc > from ctypes import * > > def test(): > s = 'abc' > a = cast(s, POINTER(c_char * 3))[0] > a[:] = 'cba' > print 'abc' > > >>> test.__code__.co_consts > (None, 'abc', 3, 0, 'cba') > > Notice that the 2nd constant in co_consts is 'abc'. This gets stored to > s and later printed. In between I use ctypes to reverse it. So what > gets printed? If you guessed "cba", you're right. > > >>> test() > cba > > Look at the constants now: > > >>> test.__code__.co_consts > (None, 'cba', 3, 0, 'cba') > > So how about referencing the abc module? > > >>> abc > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > NameError: name 'abc' is not defined > > OK, but do you think we can use cba instead? > > >>> cba > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > NameError: name 'cba' is not defined > > This is yet another problem with mucking with the internal state of an > immutable object. Equal objects are supposed to hash the same. 'cba' > is now equal to the interned 'abc' string that I reversed, but it > probes to a different slot in the dict's hash table. > > >>> test.__code__.co_consts[1] == 'cba' > True > >>> hash(test.__code__.co_consts[1]) == hash('cba') > False > > OTOH, a new 'abc' string probes to the same slot in the hash table, but > it's no longer equal (i.e. it gets handled as a hash collision). > > >>> test.__code__.co_consts[1] == 'abc' > False > >>> hash(test.__code__.co_consts[1]) == hash('abc') > True > > This breaks dict lookup unless we use the interned string itself:. > > >>> globals()[test.__code__.co_consts[1]] > <module 'abc' from '/usr/lib/python2.7/abc.pyc'> > > So the moral is only pass Python strings to C functions that promise > (scout's honor) to not modify them. If the parameter isn't const, err > on the side of caution; copy the string to a ctypes buffer. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor