ctypes & strings

Mark Tolonen metolone+gmane at gmail.com
Sat Dec 27 14:16:35 EST 2008


"Hendrik van Rooyen" <mail at microcorp.co.za> wrote in message 
news:000f01c96822$5c300f00$0d00a8c0 at hendrik...
>
> Red Rackham  wrote:
>
>>I would like to pass a string into a dll function.  I notice that to pass 
>>using
> ctypes, it has to be a ctypes type.  >Looking at the ctypes doc page I 
> don't see
> a c_string class.
>
> The following seems to work for me:
>
> In the c programme:
>
> /*
>    This routine outputs and inputs a symmetric block of bytes, writing
>    the outputs out and reading the inputs in, replacing the chars in the
>    original output string
> */
>
> unsigned char read_write (unsigned char *inputs, unsigned char *outputs, 
> int
> lenin, int lenout)
>    {
>    int i = 0;
>    int addr = 0;
>    int addrhi = 0;
>    int oind = 0;
>    char rv;
>    while (i < lenin)
>        {
>        addrhi = i >> 8 & 0x3f;     // we can have 64 * 256 adresses in the 
> top
> 6 + 8 bits
>        addr = i & 0xff;            // this is low order
>        rv = put_1(addrhi|0xd0);    // put out the addy
>        rv = put_3(addr);
>        rv = put_1(addrhi|0x90);    // make a read strobe on bit 6
>        inputs[i] = get_0() ^ 255;  // read the char
>        rv = put_1(addr|0xd0);      // raise strobe again
>        i++;
>        }
>
>    while (i < lenin + lenout)
>        {
>        oind = i - lenin;           // index into outputs start at 0
>        addrhi = i >> 8 & 0x3f;     // we can have 64 * 256 adresses in the 
> top
> 6 + 8 bits
>        addr = i & 0xff;            // this is low order
>        rv = put_1(addrhi|0xd0);    // put out the addy
>        rv = put_3(addr);
>        rv = put_0(outputs[oind]);  // put out the output
>        rv = put_1(addrhi|0x50);    // make a write strobe on bit 7
>        rv = put_1(addrhi|0xd0);    // raise write strobe again
>        i++;
>        }
>    return *inputs;
>    }
>
>
> Then in the python it is used as follows:
>
> import sys, os, ctypes, time
>
> io = ctypes.cdll.LoadLibrary('./lib_gpio.a')
>
> def do_io(ins, outs): # ins and outs are normal python strings that must 
> exist
>
>        # this routine happens to work by side effect - the ins string is
> changed by the c routine
>
>     r = io.read_write(ins,outs,len(ins),len(outs))
>     return
>
> The c routine will actually break Python's normal string
> immmutability and give you back a changed ins.
>
> It is in general not a good idea to change the passed string
> like I am doing - but you wanted to know how
> to pass a python string, and the outs example should get
> you going - a string is an array of characters in c...

Here's an example using mutable buffers:

------------ x.c --> x.dll -----------------------
#include <string.h>

__declspec(dllexport)
int fill(char *buf,int len)
{
    strncpy(buf,"initialized string",len-1);
    buf[len-1]=0;
    return strlen(buf);
}
--------------------------------------------------

PythonWin 2.6.1 (r261:67517, Dec  4 2008, 16:51:00) [MSC v.1500 32 bit 
(Intel)] on win32.
Portions Copyright 1994-2008 Mark Hammond - see 'Help/About PythonWin' for 
further copyright information.
>>> from ctypes import *
>>> x=CDLL('x.dll')
>>> s=create_string_buffer('string',10)
>>> s.raw
'string\x00\x00\x00\x00'
>>> s.value
'string'
>>> x.fill(s,len(s))
9
>>> s.raw
'initializ\x00'
>>> s.value
'initializ'
>>> s=create_string_buffer('string',20)
>>> x.fill(s,len(s))
18
>>> s.raw
'initialized string\x00\x00'
>>> s.value
'initialized string'

--Mark





More information about the Python-list mailing list