ctypes, function pointers and a lot of trouble

MRAB google at mrabarnett.plus.com
Tue Jun 3 10:40:38 EDT 2008


On Jun 3, 11:22 am, Matt <mr.e... at gmx.at> wrote:
> Hello!
>
> ouch, I should have seen that c_char... :S Well, I guess I just prove
> that it's useless to go to work and do some programming while having a
> headache like I had yesterday...
>
> okay well, back to topic:
>
> The DLL function seems to accept my parameters now, but unfortunately
> Python terminates after the DLL gets the result from the "open" callback
> function (at least its printouts are the last I get before it
> terminates). So without any kind of error message it's getting more
> difficult now.
>
> Well, since I didn't invest much time into my callback functions I
> suspect the error must be somewhere in there.
>
> This is my code:
>
> ------------------------------CODE-----------------------------------------
>
> class MemStreamData(Structure):
>      _fields_ = [("mode", c_byte),
>                       ("lPos", c_uint),
>                       ("dwVisibleSize", c_uint),
>                       ("dwBufferSize", c_uint),
>                       ("cpBuffer", POINTER(c_char))]
>
> class FilStreamData (Structure):
>      _fields_ = [("szFileName", c_char * 30),
>                       ("hFile", c_uint)]
>
> def pystreamopen (contextH, mode, pErr=0):
>      print "opening..."
>      print contextH
>      print mode
>      print pErr
>      return 0
>
> cstreamopen = CFUNCTYPE(c_uint, c_ushort, c_uint)
>
> def pystreamclose (contextH, pErr):
>      print "closing..."
>      return 0
>
> cstreamclose = CFUNCTYPE(c_uint, c_uint)
>
> def pystreamread (contextH, pBuf, pBufsize, pErr):
>      print "reading..."
>      return 0
>
> cstreamread = CFUNCTYPE(c_uint, c_void_p, c_uint, c_uint)
>
> def pystreamtell (contextH, pErr):
>      print "telling..."
>      return 0
>
> cstreamtell = CFUNCTYPE(c_uint, c_uint)
>
> def pystreamseek (contextH, origin, offset, pErr):
>      print "seeking..."
>      return 0
>
> cstreamseek = CFUNCTYPE(c_uint, c_uint, c_uint, c_uint)
>
> def pystreamwrite (contextH, origin, offset, pErr):
>      print "writing..."
>      return 0
>
> cstreamwrite = CFUNCTYPE(c_uint, c_void_p, c_uint, c_uint)
>
> class cdStream(Structure):
>      _fields_ = [("contextH", POINTER(MemStreamData)),
>                       ("open", cstreamopen),
>                       ("close", cstreamclose),
>                       ("read", cstreamread),
>                       ("write", cstreamwrite),
>                       ("seek", cstreamseek),
>                       ("tell", cstreamtell)]
>
> -----------------------------/CODE-----------------------------------------
>
> This is the way I create the vars:
>
> ------------------------------CODE-----------------------------------------
>
>      databuf = create_string_buffer(100000)
>      cbuffer=MemStreamData()
>      cbuffer.mode = c_byte(0)
>      cbuffer.lPos = c_uint(0)
>      cbuffer.dwVisibleSize = 100000
>      cbuffer.dwBufferSize = 100000
>      cbuffer.cpBuffer = databuf
>
>      stream = cdStream()
>      stream.contextH = POINTER(MemStreamData)(cbuffer)
>      stream.open = cstreamopen(pystreamopen)
>      stream.close = cstreamclose(pystreamclose)
>      stream.write = cstreamwrite(pystreamwrite)
>      stream.tell = cstreamtell(pystreamtell)
>      stream.read = cstreamread(pystreamread)
>
>      data = cdStgMedium()
>      data.Type = c_uint(1) # 0...FilStream 1...MemStream
>      data.u.pStream = POINTER(cdStream)(stream)
>
>      errorcode = cdsdk.CDGetReleasedData(devicehandle, byref(cbfunct),
> c_uint(0), c_uint(0), byref(datainfo), POINTER(cdStgMedium)(data))
>
> ------------------------------/CODE-----------------------------------------
>
> Now I have two problems:
>
> 1st: since contextH is not a c_uint (and pErr is a pointer) as I thought
> earlier, I tried to change my definition of the open function to:
>
> cstreamopen = CFUNCTYPE(POINTER(MemStreamData), c_ushort, POINTER(c_uint))
>
> unfortunately that throws an error when I try to:
>
> stream.open = cstreamopen(pystreamopen)
>
> 2nd: as may saw, I defined "def pystreamopen (contextH, mode, pErr=0)".
> The pErr variable should be a pointer to a c_uint where my function can
> tell the DLL that opening the stream went well (or give some errorcode).
>
> When I do not define pErr=0 and simply say pErr, I get the following error:
>
> Traceback (most recent call last):
>   File "\loewis\25\python\Modules\_ctypes\callbacks.c", line 206, in
> 'calling callback function'
> TypeError: pystreamopen() takes exactly 3 arguments (2 given)
>
> At first I thought okay, maybe there's no pErr and there's some error in
> the C-Code, but when I do "def pystreamopen (contextH, mode)" I get the
> same Error with:
> TypeError: pystreamopen() takes exactly 3 arguments (2 given)
>
> Any ideas?
>
> And another question: my callback functions are all defined as void...
> in C. That means that there shouldn't be anything returned. I tried this
> by using the pass statement, but got an error that returntype int was
> expected. Also "return" or "return None" don't work. Why?
>
> Puh, long mail again... hope you're so kind again and take the time to
> help me out.
>
The docs say CFUNCTYPE(restype, *argtypes), so:

cstreamopen = CFUNCTYPE(c_uint, c_ushort, c_uint)

is saying that the result type is c_uint, not void. I think you need:

cstreamopen = CFUNCTYPE(None, c_uint, c_ushort, c_uint)

instead.



More information about the Python-list mailing list