How to use dialog.h in a c program - c

I am trying to use dialog.hin my C program. For this I looked up the manual (man 3 dialog) and used the example code, which they have provided. This is how my C program look like (it is called main.c):
#include <dialog.h>
int main(void)
{
int status;
init_dialog(stdin, stdout);
status = dialog_yesno(
"Hello, in dialog-format",
"Hello World!",
0, 0);
end_dialog();
return status;
}
After research I figured out, that the dialog program is based on ncurses. So I have installed both libraries, which contains the required header files.
I am working on Debian so:
apt install dialog libncurses5-dev libncursesw5-dev
In the next step I have called the compiler, and I have also linked the libraries: gcc main.c -ldialog -lncurses
But compiling did not succeed.
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(util.o): In function `dlg_auto_size':
(.text+0x1a06): undefined reference to `sqrt'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(trace.o): In function `dlg_trace_win':
(.text+0x29c): undefined reference to `win_wch'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(trace.o): In function `dlg_trace_win':
(.text+0x2ab): undefined reference to `wunctrl'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_arrows2':
(.text+0x2c4): undefined reference to `_nc_wacs'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_arrows2':
(.text+0x2d6): undefined reference to `wadd_wch'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_arrows2':
(.text+0x43c): undefined reference to `_nc_wacs'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_arrows2':
(.text+0x44e): undefined reference to `wadd_wch'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_scrollbar':
(.text+0x878): undefined reference to `_nc_wacs'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(arrows.o): In function `dlg_draw_scrollbar':
(.text+0x88f): undefined reference to `wvline_set'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(inputstr.o): In function `dlg_index_columns':
(.text+0x932): undefined reference to `setcchar'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(inputstr.o): In function `dlg_index_columns':
(.text+0x93c): undefined reference to `wunctrl'
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libdialog.a(ui_getc.o): In function `dlg_getc':
(.text+0x603): undefined reference to `wget_wch'
collect2: error: ld returned 1 exit status
After research I found out that the missing references to some functions like win_wch, wunctrl, etc. are all defined in curses.h.
Regarding to this post (What's the difference between -lcurses and -lncurses when compiling C using ncurses lib?) ncurses and curses are the same due curses is linked to ncurses.
But anyway, I have tried to compile with the curses library too: gcc main.c -lcurses -lncurses -ldialog. But it did not work either.
What am I missing? Why did compiling fail?

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.

Related

GCC gives undefined reference when using pkg-config to link with the XCB library

I'm following an X11 programming tutorial from here. The page gives 2 commands that can be used to compile an XCB-based program:
gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
and
gcc -Wall prog.c -lxcb
Now, I've tried both. The first one says gcc: error: unrecognized command-line option ‘--cflags’. Apparently this is a shell related problem (As I've seen here). So I tried bash. And this gives a different error:
/usr/bin/ld: /tmp/ccnURTF3.o: in function `useXlib':
example.c:(.text+0xd6): undefined reference to `XInternAtom'
/usr/bin/ld: /tmp/ccnURTF3.o: in function `useXlibProperly':
example.c:(.text+0x163): undefined reference to `XInternAtoms'
/usr/bin/ld: /tmp/ccnURTF3.o: in function `main':
example.c:(.text+0x4b1): undefined reference to `XOpenDisplay'
/usr/bin/ld: example.c:(.text+0x559): undefined reference to `XCloseDisplay'
collect2: error: ld returned 1 exit status
This is the same as what I get with gcc -Wall prog.c -lxcb. So I guess bash fixed the problem but there are 2. And in Atom, when you hover over a function, it shows you which header it is from. But in this one I didnt't get anything.
Thanks in advance
Looks like over the years the libraries got splitted and the function declarations were moved to a different library. And now xcb depends on X11 or something like that or maybe pkg-config --libs xcb should output -lX11, no idea. Anyway, the following works:
gcc -Wall 1.c -lxcb -lX11
or the following works too:
gcc -Wall 1.c $(pkg-config --cflags --libs xcb) $(pkg-config --cflags --libs x11)
Would be nice to ping the maintainer of that introduction to let him know he should update the page.

undefined reference to `SDL_Init', linking SDL to program

I am beginning to use the SDL library for the first time and I used the apt-get install to download it onto the windows subsystem (Ubuntu). When I make calls to functions from the SDL library and then run the makefile, I am presented with:
/home/display.c:13: undefined reference to `SDL_Init'
/home/display.c:14: undefined reference to `SDL_GetError'
/home/display.c:17: undefined reference to `SDL_CreateWindow'
/home/display.c:19: undefined reference to `SDL_GetError'
/home/display.c:22: undefined reference to `SDL_CreateRenderer'
/home/display.c:24: undefined reference to `SDL_GetError'
The makefile looks like:
gcc -Wall -Werror -Wextra -Wunused -std=gnu99 -g -O0 -Wpedantic -lpthread -lSDL2main -lSDL2
I believe the issue is in linking and that the compiler cannot find where SDL is. However, if this were the case, there should be an error stating that #include SDL2/SDL.h cannot be found. Could this be an installation issue or an issue with the way I link SDL in the makefile?
The order in which I was placing the flags was incorrect. The libraries should be after the .c and .h files.

libpdcurses.a setting for Pdcurses

I'm working on a program in which I use PDCurses3.5 functions using i686-w64-mingw32-gcc.exe.
When I compile the program, I keep getting errors such as "undefined reference to 'COLS'", "undefined reference to 'lines'".
I have checked that <curses.h> header and the library package properly installed.
Here is my input line:
> i686-w64-mingw32-gcc.exe set.o read.o elements.o random.o
> -L../standard/test -lplotfit -lplotget -lgfortran -Wl,--subsystem,console -mwindows -o runtime/mingw/result -lm -static -lws2_32 -lpdcurses
And the first part of the error is:
../standard/bin/mingw/menu.o:menu.c:(.text+0xb): undefined reference to `COLS'
../standard/bin/mingw/menu.o:menu.c:(.text+0x16): undefined reference to `COLS'
../standard/bin/mingw/menu.o:menu.c:(.text+0x33): undefined reference to `LINES'
../standard/bin/mingw/menu.o:menu.c:(.text+0x47): undefined reference to `MOVE'
../standard/bin/mingw/menu.o:menu.c:(.text+0x74): undefined reference to `initscr'
...
It seems the program cannot refer to libpdcurses.a in its library file.
What am I doing wrong?
When you use -lpdcurses, the linker looks for libpdcurses.a in certain predefined locations, plus those specified via -L. But, by default, the library is built as pdcurses.a. To link it, you can directly specify its location; e.g.:
gcc -oprogname.exe progname.c pdcurses.a
or
gcc -oprog2.exe prog2.c /pdcurses/win32/pdcurses.a
Alternatively, you can rename the library to libpdcurses.a, and either copy it to a location in the existing search path, or use -L:
gcc -oprogname.exe progname.c -lpdcurses
or
gcc -oprog2.exe prog2.c -L/pdcurses/win32 -lpdcurses

Properly Linking a static library with the C math library

I have a library which uses the log function from math.h. When I compile and package this library, I get no compilation errors, which is normal (I think).
Now when I try to use the library in an application, gcc gives me linker errors:
Compiling mytestlist using "mytestlist.o":
gcc mytestlist.o -I/student/cmpt332/pthreads -I. -std=c99 -Wall -pedantic -L. -L/student/cmpt332/pthreads/lib/linuxx86_64/ -llist -o mytestlist
./liblist.a(list_adders.o): In function `NodeCreate':
list_adders.c:(.text+0x343): undefined reference to `log'
./liblist.a(list_adders.o): In function `ListCreate':
list_adders.c:(.text+0x62f): undefined reference to `log'
./liblist.a(list_adders.o): In function `ListFree':
list_adders.c:(.text+0xdcc): undefined reference to `log'
list_adders.c:(.text+0xe55): undefined reference to `log'
list_adders.c:(.text+0xefb): undefined reference to `log'
./liblist.a(list_adders.o):list_adders.c:(.text+0xf96): more undefined references to `log' follow
collect2: error: ld returned 1 exit status
Makefile:47: recipe for target 'mytestlist' failed
make: *** [mytestlist] Error 1
Why is this happening? The only solution that works is that I have to supply the -lm option to gcc when I compile the program that uses the library (even though the program itself makes no use of math.h), however I find this cumbersome to do.
I've also tried supplying the -lm option when compiling the library, but when the application is compiled using the library, I get the same linker errors.
Is there a way to compile the library with math.h without having to supply -lm to other programs that make use of the library?
In case you're wondering, I compile each object that makes up the library using:
gcc -std=c99 -Wall -pedantic -static -I. -c list_adders.c -o list_something.o -lm
And the library is packaged using:
ar cvfr liblist.a list_something.o ...
In your gcc -c command, the -lm isn't doing anything. It's a linker option, and -c means "don't link".
The proper place to put -lm is in fact after the -llist whenever you use it. That's how static library dependencies are done. Put it in the documentation for liblist.
If you want something fancier, there's pkg-config. With the appropriate configuration files, pkg-config --static --libs liblist will output -llist -lm.

No undefined references when compiling shared library

Im wondering why Im getting no undefined references when compiling as a shared library using -shared as an option for gcc. Consider the following case:
#include <confuse.h>
int
main(int argc, char **argv)
{
cfg_opt_t opts[1];
cfg_t *cfg = cfg_init(opts, CFGF_NOCASE);
return 0;
}
libconfuse is needed here in order to run the program properly. If im compiling it as a "normal" application without specifying that libconfuse is needed (-lconfuse) im getting the following (from my perspective regular) error:
$ gcc -Wall -Wno-unused-variable test.c -o test
/tmp/ccTVz6an.o: In function `main':
test.c:(.text+0x20): undefined reference to `cfg_init'
collect2: error: ld returned 1 exit status
If im compiling the same code as a shared library im not getting any error message regarding the library:
$ gcc -Wall -Wno-unused-variable test.c -o test.so -shared
$ echo $?
0
Can someone please bring light into darkness?
You are compiling a (shared) library, not a program, and libraries are expected not to be complete, so undefined references do not prevent the shared library from building.
Yes, it may sound a bit surprising, particularly if you come from a OS (Windows?) where the shared libraries are always fully linked, but that's how ELF works.
If you want to ensure that all your references are are resolved when building a shared library you can use the linker option --no-undefined:
gcc -Wall -Wno-unused-variable test.c -o test.so -shared -Wl,--no-undefined
Note that libraries used to resolve references when linking a shared library will be added to the header of that library, as NEEDED entries, and then linked automatically when using that library. See objdump -p for details.
With shared libraries (not static ones), you could link a library libA.so into your other library libB.so.
So you could compile your shared library as:
gcc -Wall -Wno-unused-variable -fPIC test.c \
-o libmytest.so -shared -lconfuse
Later you would link that library to some main.c with
gcc -Wall main.c -lmytest -L. -o myprog
or you could load it at runtime, using dlopen(3) on ./libmytest.so (read the man page about why ./ is significant to dlopen)
Simple explanations are in the Program Library HowTo. But Drepper's paper: How to Write Shared Libraries is the best reference.
And it is permitted for a shared library (or even a static one) to have undefined references, since quite often the user of that library would explicitly link the lower level libraries needed by it.

Resources