Building Helloworld C++ Program in Linux with Ncurses

Not able to compile C/C++ code that's using ncurses

you have to link the ncurses library

g++ -o hello_world hello_world.cpp -lncurses

Undefined reference when using ncurses on linux

Have you used the -lcurses option when linking?

Including the header files let the code compile (because the compiler knows what the function call looks like from the .h file), but the linker needs the library file to find the actual code to link into your program.

how to make ncurses program working with other linux utils?

Pipes use the standard output (stdout) and standard input (stdin).

The simplest way - rather than using initscr, which initializes the output to use the standard output, use newterm, which allows you to choose the file descriptors, e.g.,

newterm(NULL, stderr, stdin);

rather than

initscr();

which is (almost) the same as

newterm(NULL, stdout, stdin);

By the way, when you include <ncurses.h> (or <curses.h>), there is no need to include <stdio.h>.

If you wanted to use your program in the middle of a pipe, that is more complicated: you would have to drain the standard input and open the actual terminal device. But that's another question (and has already been answered).

Further reading:

  • initscr, newterm, endwin, isendwin, set_term, delscreen -
    curses screen initialization and manipulation routines

How to use dialog.h in a c program

I did some testing on a Debian-based system (a Beaglebone), and this was not an obvious fix. Turns out there are multiple versions of the ncurses library, and the dialog library was built with one of them, just not the one you were using.

The way you're supposed to figure this out is with the dialog-config command, which has options to show which CFLAGS or libraries you need on the compile line (or in the makefile), but I didn't find it on my system, so I looked at /usr/include/dlg_config.h for some clues:

...
#define DLG_HAVE_LIBINTL_H 1
#define DLG_HAVE_LIBNCURSESW 1 <---
#define DLG_HAVE_LIMITS_H 1

Hmmm, this suggests it needs -lncursesw instead of -lncurses, so we see this compile:

$ gcc dlg.c -ldialog -lncursesw
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/8/../../../arm-linux-gnueabihf/libdialog.a(util.o): in function `dlg_auto_size':
(.text+0x13d2): undefined reference to `sqrt'

Ok, so a lot closer: sqrt() is in the math library, so adding -lm gets it over the goal line:

$ gcc dlg.c -ldialog -lncursesw -lm

It seems that ncursesw is a wide-character version that works with an international character set, which was new to me.

EDIT: Elaborating on the "dialog-config" stuff: The way you're supposed to do this is documented in the dialog(3) manual page:

gcc $(dialog-config --cflags) file ... $(dialog-config --libs)

The idea is that a package can publish what it needs to build in a command, so in this case I imagine that dialog-config --cflags might not output anything, but dialog-config --libs would output -ldialog -lncursesw -lm, so you could embed this in your makefile and have it do the right thing.

This paradigm is common, and on my system I see (for example) /usr/bin/python-config that shows how it was built on this machine:

$ python-config --cflags
-I/usr/include/python2.7 -I/usr/include/arm-linux-gnueabihf/python2.7
-fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g
-fdebug-prefix-map=/build/python2.7-RT6aMn/python2.7-2.7.16=.
-fstack-protector-strong -Wformat -Werror=format-security -DNDEBUG
-g -fwrapv -O2 -Wall -Wstrict-prototypes

$ python-config --libs
-lpython2.7 -lpthread -ldl -lutil -lm

If you were trying to build some kind of Python plugin, guessing the above parameters would be a real challenge.

Statically link ncurses to program

You need to pass -l options at the end of the command line:

gcc -static hello_curses.c -o curses -lncurses

When the compiler encounters -lfoo, it links in all the symbols from foo that have been requested by a previous file. If you put -lfoo at the beginning, no symbol has been requested yet, so no symbol gets linked.

How do these different gcc linking options change the final executable?

This is most likely the way you want to build it:

gcc test.c -o test -lncurses

This says: "compile test.c, name the output file test and dynamically link the library (or shared object) called libncurses.so (the lib prefix is automatically added).

Note that the .exe suffix is not used on Linux, just Windows (your question is tagged with linux so I assume that is the platform you are using here).

If you statically link like this:

gcc -static test.c -o test.exe -lncurses

then the linker will look for a static version of the library (ie. libncurses.a). You get a whole bunch of linker errors, as it cannot resolve the references to the library functions, which suggests you don't have a static version of the library. Unless you have a really good reason to link statically, the norm is to use dynamic linking.

The next command just specifies some additional (but redundant) library paths:

gcc -static test.c -o test.exe -L/usr/lib -lncurses

This is simply telling the linker to search in /usr/lib when looking for libraries. However, /usr/lib is already in the default path, so this shouldn't ordinarily make a difference. If you run gcc -dumpspecs it will print all the paths and definitions that have been 'baked in' to the tool, and thus what the default search paths are for include files, libraries and so on.

The /usr/lib directory has a libncurses.a file (amongst others) while the /usr/include contains a an ncurses.h symlinked to curses.h and an ncurses_dll.h. Is perhaps the libncurses.a file not a dynamic library? What is ncurses.h then?

The symlinks are present for backwards compatibility. The ncurses library (for "new curses") supersedes the original curses, but provides curses.h so old code can still build and run. The ncurses_dll.h header provides some definitions only used for compiling on cygwin or MSVC under Windows, so you can ignore it. The ncurses.h is the real primary header for the library, and should be used for new code.



Related Topics



Leave a reply



Submit