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
Core Dump of Multithreaded Application Shows Only One Thread
Does Each Unix File Description Have Its Own Read/Write Buffers
Is Overwriting a Small File Atomic on Ext4
How to Grep for Strings with Special Characters Like []
How to Pass Local Variable to Remote Using Ssh and Bash Script
How to Efficiently Move Many Files to a New Server
Why Does The Solaris Assembler Generate Different Machine Code Than The Gnu Assembler Here
Reading Serial Port Blocks for Unknown Reason
Installing 32 Bit Libraries (Glibc) on 64 Bit Rhel Without Using Yum
How Does Linux Kernel Creates Sysfs
Linux X86 Nasm - Subroutine: Print a Dword from Eax
How to Use Performance Counters Inside of The Kernel
How to Configure Gitlab as a Subdomain in Nginix.Conf
How Does Ltrace (Library Tracing Tool) Work