6

I am trying to pass a file descriptor through ctypes, to a C function where writes are performed on the fd. On linux it works. On windows it doesn't and I don't understand why (I have no experience as a developer on windows)

//C func signature: 
void fun(struct bah *opaque, int fd)

from python (details ommited):

mylib.fun.argtypes = [POINTER(bah), c_int]
fh = open(filename,'wb')
#doesn't work on windows, works on linux/unix
mylib.fun(some_ctypes_struct, fh.fileno())
#doesn't work on windows
mylib.fun(bah_struct, ctypes.cdll.msvcrt._open(filename,_O_FLAGS_MASK, ACCMASK)
#doesn't work
mylib.fun(bah_struct, os.open(...))

program dies on write()s with a failed assertion _osfile(fh) & FOPEN

cl.exe: 16.00.40219.01 for x86 python 2.7.2 msc v.1500 32bit

how am I supposed to do it? no, I don't want to offload open() to lib. I want to pass an already open file descriptor in a safe manner, platform independent.


additional information, just in case: the library is tinycdb, I ported it quickly to windows with a short cmake spec and few dirty patches to make getopt and dll exports work. the library and the exe tool works as expected (tested). the python ctypes wrappers for tinycdb works on linux as expected. windows gives me eyeballs. he wont accept the fd is a valid descriptor even if I'm passing it after opening it with its own (msvcrt) _open libcall.


ofcourse, everything works if I'm open()ing/close()ing the file within the library but I can't afford to change the API.

user237419
  • 8,829
  • 4
  • 31
  • 38
  • 1
    Is the same C library (msvcrt) being used by both Python and your DLL? (http://www.dependencywalker.com/ is one way to check.) – jdigital Feb 08 '12 at 23:53

1 Answers1

4

Windows doesn't use file descriptions like Unix does, so I'm hypothesizing that file descriptors are emulated by the C runtime. If you are using two different C runtimes (for example, if your EXE and DLL are compiled by different compilers, or with the same compiler but with different options), then each runtime will have its own "file descriptor emulation" and you can't pass a descriptor from one to the other.

jdigital
  • 11,926
  • 4
  • 34
  • 51
  • python seems to be compiled with 9.0, my dll uses 10.0. however, I'm still digesting OS file handles and C runtime file descriptors as being different beasts. Either I'm using 9.0 and 10.0 runtimes together, shouldn't my fd "emulator" map to the same OS file handle? – user237419 Feb 09 '12 at 05:56
  • or is it that each runtime has its own "descriptor table" mapping the fds to OS file handles? in this case the error would make sense since my fd is in crt90's table and i'm searching for it in crt10's table. is this how it works? thanks jdigital! – user237419 Feb 09 '12 at 06:04
  • I think you already answered my question but the "hypothesis" decorator makes me ask for more, sorry. – user237419 Feb 09 '12 at 06:11
  • The "separate descriptor table" hypothesis is most likely. BTW, there's a similar problem with malloc: if you have two implementations of malloc (each with its own heap), and then use malloc from one library and free from another, you'll have problems. – jdigital Feb 09 '12 at 18:57