How to show printf stderr/stdout in IDLE

9 views
Skip to first unread message

v...@viblo.se

unread,
Jul 21, 2024, 3:22:27 PM7/21/24
to python-cffi
In a python I have a python library Im maintaining that uses CFFI together with a underlying c library. The c-library sometimes uses printf and related to print information to the user.

This becomes a problem when running in IDLE, because when the c-code prints it does not show up in IDLE (if IDLE was started from terminal it will show up there). It is extra troublesome because (at least in my experience) many newbies use IDLE and become very confused.

Is there a smart way to handle this situation?

Thanks!
Victor

Armin Rigo

unread,
Jul 21, 2024, 6:08:39 PM7/21/24
to pytho...@googlegroups.com
Hi Victor,
This should ideally be a feature of IDLE, but I understand perfectly
well if you don't want to wait an unbounded amount of time for it to
be fixed. Instead, you can do that by adding a little bit of pure
Python code. Here's an old comment on the IPython github project that
is relevant in your case too:
https://github.com/ipython/ipython/issues/1230#issuecomment-58423726

After doing `os.dup2(..., 1)`, any C-level `printf()` will be
redirected into the pipe, and the background thread reads that pipe
and sends it to the Python-level `sys.stdout`. For Python 3, you
likely need to decode the bytes into strings in that background
thread. (According to that comment, the Windows solution is different.)


A bientôt,
Armin Rigo

Victor Blomqvist

unread,
Jul 22, 2024, 3:44:44 PM7/22/24
to pytho...@googlegroups.com
Thanks for the reply! 

In my case windows support is important. Many users there..
On the other hand, I don't need to do some generic solution, it's enough it works for my case, and I could even modify (within reason) the c-library Im using. 

I got another idea from that comment thread: Its not possible to call PySys_WriteStdout and related functions from the c-code with CFFI, is it? (Before reading the thread I played with a solution where I created a printf-like c-function, that just calls into python. And then on the python side called print, but it was quite a roundabout way for this small feature I felt)

/Victor

--
-- python-cffi: To unsubscribe from this group, send email to python-cffi...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/python-cffi?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "python-cffi" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python-cffi/NHdYFgYArVw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python-cffi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python-cffi/CAMSv6X10sdye1ENurUPww06qi-Lfj2arFrhy27iRVBEfhV_W8A%40mail.gmail.com.

Armin Rigo

unread,
Jul 23, 2024, 6:12:58 AM7/23/24
to pytho...@googlegroups.com
Hi,

On Mon, 22 Jul 2024 at 21:44, Victor Blomqvist <v...@viblo.se> wrote:
> In my case windows support is important. Many users there..
> On the other hand, I don't need to do some generic solution, it's enough it works for my case, and I could even modify (within reason) the c-library Im using.
>
> I got another idea from that comment thread: Its not possible to call PySys_WriteStdout and related functions from the c-code with CFFI, is it?

No, you can't reasonably call PyXxx functions from C code in CFFI
(there are hacks to do it). Better is to make a CFFI callback:

ffibuilder.cdef("""
extern "Python" void _print(const char *);
""")

and at runtime:

from _my_example import ffi, lib
@ffi.def_extern()
def _print(msg):
sys.stdout.write(ffi.string(msg).decode('utf-8', 'replace'))
# or log it, or do whatever

From the C code, you either directly call _print("somestring\n");, or
you make a wrapper for varargs, something like this which you can put
into ffi.set_source():

void my_printf(const char *format, ...)
{
va_list args;
char buffer[SOME_MAXIMUM_SIZE];
buffer[0] = 0;

va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);

_print(buffer);
}

Then you compile the library with these lines added to some header:

extern void my_printf(const char *format, ...);
#define printf my_printf // optionally, will replace all calls
to printf automatically


Hope this helps,

Armin

Victor Blomqvist

unread,
Jul 23, 2024, 3:46:20 PM7/23/24
to pytho...@googlegroups.com
Thanks for the detailed answer! I think I know my options now, and will do some experimentation.

/Victor

--
-- python-cffi: To unsubscribe from this group, send email to python-cffi...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/python-cffi?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "python-cffi" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python-cffi/NHdYFgYArVw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python-cffi...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages