[Tutor] ctypes question

Alan Gauld alan.gauld at btinternet.com
Wed Oct 10 13:24:31 CEST 2012

On 10/10/12 11:02, Albert-Jan Roskam wrote:
> I have a program that reads and writes files using ctypes.

Any particular reason why? That's not normally something I'd expect you 
to need ctypes for. Unless you just want to play with ctypes...

> When I want it to read AND write (e.g. read a file, select some stuff and write that),
 > the library returns a 'read-open' error.

Can we see the error messages please?

> I think that the pointer to the file handle for read and write point to the same address.
 > To test that hypothesis, I wrote the simplified code below.
 > Problem is, that I can't make it work

Again, what exactly is going wrong. "can't make it work is not too 
helpful, we need specific descriptions of what went wrong with any error 

> How do I tell ctypes to use a particular chunck of memory,
 > so read and write buffers do not mutually interfere?

In general you don't, you leave all that to the OS via the C libraries.
But you do need to think about what you are doing with the file. You 
shouldn't open the same file simultaneously for read and write. If you 
do need to do both use the combined 'rw' mode - but be aware that 
getting simultaneous read/write behaviour right is hard!

> Maybe the 'offset' parameter of ctypes.byref?
> import ctypes
> import platform
> import os
> import tempfile
> # load libraries
> pf = platform.platform().lower()
> if pf.startswith("win"):
>      libc = ctypes.cdll.msvcrt
>      fopen = libc._fdopen
> elif pf.startswith("lin"):
>      libc = ctypes.CDLL("libc.so.6")
>      fopen = libc.fdopen
> elif pf.startswith("darwin"):
>      libc = ctypes.CDLL("libc.dylib")
>      fopen = libc.fdopen
> else:
>      raise NotImplementedError
> # create test data
> path = tempfile.gettempdir()
> os.chdir(path)
> fn = "test.txt"
> lines = 100 * (100 * "*" + os.linesep)
> with open(fn, "wb") as f:
>      f.write(lines)
> # read test data (code does NOT work)
> fh = fopen(ctypes.c_char_p(fn), "rb")
> fhPtr = ctypes.byref(ctypes.c_int(fh))
> buff = ctypes.create_string_buffer(lines)
> ret = libc.fread(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fhPtr)
> print buff.value
> # write test data (code does NOT work)
> fn = "somefile.txt"
> fh_out = fopen(ctypes.c_char_p(fn), "wb")
> fh_outPtr = ctypes.byref(ctypes.c_int(fh_out))
> buff = ctypes.create_string_buffer(lines)
> ret = libc.fwrite(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fh_outPtr)

Again, what does "NOT work"? Does it work if you comment out one of the 
blocks? I don't use ctypes much and certainly not for file handling so 
can't be sure if the code is correct or not - maybe ask on a ctypes 
forum for that...

Alan G
Author of the Learn to Program web site

More information about the Tutor mailing list