0

I am not have any success with this situation.

On Ubuntu 14 with Python 3.5.1, I want to pass sys.stdin to C/C++ with only ctypes and use libc.fscanf. I have tried libc.stdin as well. I believe this has to be done in binary because that is how Python 3 ctypes need things. Some posts suggest using libc.freopen but i still have the following problem.

I believe that the first argument to fscanf which is a file pointer (or file descriptor) gives me seg faults.

How do I go about doing this?

mszlazak
  • 59
  • 1
  • 6
  • You can call `scanf` to read from stdin. For example: `s = (c_char * 100)();` `d = c_int();` `libc.scanf(b"%s %d", s, byref(d))`. Say you enter "abcde 12345". Then `s.value == b'abcde'` and `d.value == 12345`. – Eryk Sun May 08 '16 at 07:41
  • Thanks and I already have that solution which works but does not use your s. What, I need is an approach that uses fscanf. This then raises the issue of passing it's first argument which maybe a file pointer or file descriptor. In binary format for stdin of course. – mszlazak May 08 '16 at 12:03
  • If you need to read the stdin `FILE` pointer, that's what `scanf` is for. If you need to read some other open file that's not stdin, then you need to get a `FILE` pointer by either calling `fopen` for a file path or `fdopen` for an existing file descriptor. Set the `restype` of the function to an opaque `FILE` pointer, e.g. `class _FILE(Structure): pass;` `FILE = POINTER(_File);` `libc.fopen.restype = FILE`. – Eryk Sun May 08 '16 at 21:39
  • Ok but there is more to this! I need to deal with a speed issue for a contest submission which requires shaving off a small amount of time from a last test case. If I use fscanf, I maybe able to get what i need since it runs a bit faster ... at least on my machine. So then the issue of binary format for stdin also has to be addressed. The way the challenges are set up require that data is read via stdin. Not my rules. – mszlazak May 09 '16 at 05:02
  • Thank you! You gave me what i needed to make it work! from ctypes import *; libc = cdll.LoadLibrary("libc.so.6"); class FILE(Structure): pass; freopen.restype = POINTER(FILE); f = freopen(None, b'rb', c_void_p.in_dll(libc, 'stdin')); input = c_int(); libc.fscanf(f, b"%d", byref(input)); print(input.value); – mszlazak May 09 '16 at 17:54
  • You're not using Windows (since `libc.stdin` wouldn't work), so I see no reason to re-open `stdin` in binary mode. There's no difference on POSIX systems. Even if there were a reason to do this, it would be better to `fdopen` a new `FILE` stream for fd 0 (or `fileno(stdin)`) than to rebind stdin via `freopen`. – Eryk Sun May 09 '16 at 18:05
  • Ok but i am not sure what you mean by rebinding stdin via freopen. f = libc.fdopen(0, b"rb") gives a fd, then what? – mszlazak May 09 '16 at 18:47
  • [`fdopen`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdopen.html) returns a `FILE` stream for a file descriptor. – Eryk Sun May 09 '16 at 19:42
  • Oops, misread "than" as "then." Yup that works. Thanks! – mszlazak May 09 '16 at 22:30

0 Answers0