How to link Wayland header files in C? - c

I am starting out with coding for Wayland. I have been following many tutorials, but I am still stuck at compiling. I wrote this very simple code:
#include<stdio.h>
#include<wayland-client-core.h>
int main(int argc, char *argv[]) {
struct wl_display *display = wl_display_connect(NULL);
if(!display) {
fprintf(stderr, "Failed to connect to Wayland display\n");
return 1;
}
fprintf(stdout, "Connection established!\n");
getchar();
wl_display_disconnect(display);
return 0;
}
Then, I tried to compile it with gcc -o client -lwayland-client client.c
But, compilation fails with this error message:
/usr/bin/ld: /tmp/ccfXeOS8.o: in function `main':
client.c:(.text+0x19): undefined reference to `wl_display_connect'
/usr/bin/ld: client.c:(.text+0x7c): undefined reference to `wl_display_disconnect'
collect2: error: ld returned 1 exit status
This looks strange because there is a file /usr/include/wayland-client-core.h in the system, which has got these declarations:
struct wl_display *wl_display_connect(const char *name);
void wl_display_disconnect(struct wl_display *display);
What am I doing wrong here?

You need to change the command line to:
gcc client.c -o client -lwayland-client
or:
gcc client.c -lwayland-client -o client
or:
gcc -o client client.c -lwayland-client
Basically, the .c file (or .o file) needs to appear before the library linking options.

Related

How to use WordNet in a C project?

I'm trying to link to WordNet library. I downloaded the header file (wn.h), libWN.a file and a bunch of .o files (libWN_a-search.o, etc) from WordNet. I put a main.c, wn.h and libWN.a files in a folder and implemented main.c:
#include <stdio.h>
#include "wn.h"
int main(int argc, char *argv[]) {
char rc, *s;
s = "cat";
rc = in_wn(s, ALL_POS);
printf("rc: %d\n", rc);
return 0;
}
I try to compile using cc main.c -L. but I get the linker error:
/usr/bin/ld: /tmp/ccvzqY4x.o: in function `main':
main.c:(.text+0x27): undefined reference to `in_wn'
collect2: error: ld returned 1 exit status
Documentation on WordNet lib can be found here. I'm just not sure what I'm doing wrong.
Including the wn.h header file is not enough. The .h file only contains the declarations, but the actual implemenation is contained in the library file libWN.a which you failed to link with.
For linking with that library you need to tell the compiler to do so by adding -lWN:
cc main.c -L. -lWN

Compiling a sample SDL2 program with gcc/cygwin on windows: undefined reference to WinMain

I browsed the whole internet and tried every solution for this, without result.
What I'm using:
Windows 10
Cygwin
gcc compiler
I'm trying to compile this simple code:
#include "SDL.h"
int main(int ac, char **av)
{
return 0;
}
This is what my makefile looks like:
hellosdl:
gcc hellosdl.c -L../SDL2-2.0.18/x86_64-w64-mingw32/lib -lSDL2main -lSDL2 -mwindows -I../SDL2-2.0.18/x86_64-w64-mingw32/include/SDL2
where -lSDL2main -lSDL2 -mwindows is the output of sdl2-config --libs, minus -lmingw32.
Output:
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: /usr/lib/gcc/x86_64-pc-cygwin/10/../../../../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.2.0-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'
collect2: error: ld returned 1 exit status
make: *** [Makefile:3: hellosdl] Error 1
What am I not understanding?

When I make a shared library, a error occur

I made a shared library as the follow:
gcc -c output.c
gcc -shared -fPIC -o liboutput.so output.o
When output.c is the follow, it could work.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
return 1+2;
}
But, when output.c changed as the follow, a error occur.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
printf("%s\n", st);
return 1+2;
}
This is error message:
/usr/bin/ld: output.o: relocation R_X86_64_PC32 against undefined 符号 `puts##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: 错误的值
collect2: error: ld returned 1 exit status
I want to know why and how to deal it. Thanks in advance.
You need to compile output.c as position independent code.
gcc -c -fPIC output.c
In the first version you have not called any library function. But in second one printf is being called. In general, compile all sources with -fPIC if you intend to build a shared library later.

I've included a header file but I still get undefined when trying to run make

I am trying to implement bcrypt into an open source project I've found, more of a learning thing. I've git cloned https://github.com/rg3/bcrypt and moved the bcrypt.h bcrypt.c and crypto_blowfish into my projects file, then in my file database.c I've
include "bcrypt.h"
Then when I run make I get:
database.c:2084: undefined reference to `bcrypt_checkpw'
This is how I'm using it
int ret;
ret = bcrypt_checkpw(pass, row[0]);
assert(ret != -1);
if (ret == 0) {
return 1;
} else {
return 2;
}
I have a Makefile I'm not sure if I did this right but I added bcrypt.h to the makefile
.obj/database.o: database.c bcrypt.h server.h log.h create.h player.h sleep.h tool.h drdata.h drvlib.h timer.h direction.h map.h mem.h database.h misc_ppd.h badip.h
All compile
gcc -O -g -m32 -rdynamic -L/usr/lib/mysql -o server .obj/server.o .obj/io.o .obj/libload.o .obj/tool.o .obj/sleep.o .obj/log.o .obj/create.o .obj/notify.o .obj/skill.o .obj/do.o .obj/act.o .obj/player.o .obj/rdtsc.o .obj/los.o .obj/light.o .obj/map.o .obj/path.o .obj/error.o .obj/talk.o .obj/drdata.o .obj/death.o .obj/database.o .obj/see.o .obj/drvlib.o .obj/timer.o .obj/expire.o .obj/effect.o .obj/command.o .obj/date.o .obj/container.o .obj/store.o .obj/mem.o .obj/sector.o .obj/chat.o .obj/statistics.o .obj/mail.o .obj/player_driver.o .obj/clan.o .obj/lookup.o .obj/area.o .obj/task.o .obj/punish.o .obj/depot.o .obj/prof.o .obj/motd.o .obj/ignore.o .obj/tell.o .obj/clanlog.o .obj/respawn.o .obj/poison.o .obj/swear.o .obj/lab.o .obj/consistency.o .obj/btrace.o .obj/club.o .obj/teufel_pk.o .obj/questlog.o .obj/badip.o -lmysqlclient -lm -lz -ldl -lpthread
.obj/database.o: In function `load_char_pwd':
/home/ec2-user/astonia3_server/database.c:2084: undefined reference to `bcrypt_checkpw'
collect2: error: ld returned 1 exit status
make: *** [server] Error 1
The bcrypt_checkpw in .h file is put on extern Cso it has C linkage
The bcrypt_checkpw in .c file has C++ linkage
They are different symbols so you will get linking error.

Including PJSIP-Library and writing makefile

im new to writing makefile. Now im trying to use pjsip c-library, which i installed in my home-directory. I took a little snipped and tried to compile it. Had some errors and so i searched for an solution, so i found out i had to include this library's to the search path. Further there is a possibility to declare them in the makefile, so i tried the 2nd solution.
Here my makefile:
pjpath=home/pi/pjproject-2.4.5
LIB=-L/$(pjpath)/pjlib/lib -L/$(pjpath)/pjlib-util/lib -L/$(pjpath)/pjnath/lib -L/$(pjpath)/pjmedia/lib -L/$(pjpath)/pjsip/lib
INC=-I/$(pjpath)/pjlib/include -I/$(pjpath)/pjlib-util/include -I/$(pjpath)/pjnath/include -I/$(pjpath)/pjmedia/include -I/$(pjpath)/pjsip/include
all:
gcc -o test $(INC) simple_pjsua.c $(LIB) -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
clean:
rm simple_pjsua.o test
and here my c-file simple_pjsua.c:
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#include <pjsua-lib/pjsua.h>
#define THIS_FILE "App"
#define SIP_USER "demo-user2"
#define SIP_DOMAIN "sip:192.168.2.59"
#define SIP_PASSWD "123456"
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata);
static void on_call_state(pjsua_call_id call_id, pjsip_event *e);
static void on_call_media_state(pjsua_call_id call_id);
static void error_exit(const char *title, pj_status_t status);
int main(int argc, char *argv[]){
printf("Hello World");
return 0;
}
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata){
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!", (int) ci.remote_info.slen, ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
}
static void on_call_state(pjsua_call_id call_id, pjsip_event *e){
pjsua_call_info ci;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id, (int) ci.state_text.slen, ci.state_text.ptr));
}
static void on_call_media_state(pjsua_call_id call_id){
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}
static void error_exit(const char *title, pj_status_t status){
pjsua_perror(THIS_FILE, title, status);
pjsua_destroy();
exit(1);
}
and this is my output of the makefile:
gcc -o test -I/home/pi/pjproject-2.4.5/pjlib/include -I/home/pi/pjproject-2.4.5/pjlib-util/include -I/home/pi/pjproject-2.4.5/pjnath/include -I/home/pi/pjproject-2.4.5/pjmedia/include -I/home/pi/pjproject-2.4.5/pjsip/include simple_pjsua.c -L/home/pi/pjproject-2.4.5/pjlib/lib -L/home/pi/pjproject-2.4.5/pjlib-util/lib -L/home/pi/pjproject-2.4.5/pjnath/lib -L/home/pi/pjproject-2.4.5/pjmedia/lib -L/home/pi/pjproject-2.4.5/pjsip/lib -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
In file included from /home/pi/pjproject-2.4.5/pjlib/include/pj/config.h:288:0,
from /home/pi/pjproject-2.4.5/pjlib/include/pj/types.h:33,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_config.h:27,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_types.h:34,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip.h:24,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsua-lib/pjsua.h:30,
from simple_pjsua.c:3:
/home/pi/pjproject-2.4.5/pjlib/include/pj/config_site.h:3:35: warning: extra tokens at end of #include directive [enabled by default]
/usr/bin/ld: cannot find -lpj
/usr/bin/ld: cannot find -lpjlib
/usr/bin/ld: cannot find -lpjnath
/usr/bin/ld: cannot find -lpjmedia
/usr/bin/ld: cannot find -lpjmedia-audiodev
/usr/bin/ld: cannot find -lpjmedia-codec
/usr/bin/ld: cannot find -lpjmedia-videodev
/usr/bin/ld: cannot find -lpjsdp
/usr/bin/ld: cannot find -lpjsip
/usr/bin/ld: cannot find -lpjsip-simple
/usr/bin/ld: cannot find -lpjsip-ua
/usr/bin/ld: cannot find -lpjsua
/usr/bin/ld: cannot find -lpjsua2
collect2: ld returned 1 exit status
makefile:6: recipe for target 'all' failed
make: *** [all] Error 1
I also found a useful site which explains how it's done, although i couldn't yet figure it out.
First of all, the first warning is from the library code, your code isn't guilty.
Then, always specify link libraries after all of your source or object files. By default GNU linker doesn't remember the symbols from libraries which haven't been referenced yet, so it simply drops out all of your -lsomelib if that somelib hasn't been referenced by a previous object or library.
So, I bet, the line
gcc -o test $(INC) simple_pjsua.c $(LIB)
would help you (or at least this particular error would be resolved).
so i found the the simplest solution at this Site, in the section makefile with version 1.6 or later.
# If your application is in a file named myapp.cpp or myapp.c
# this is the line you will need to build the binary.
all: myapp
myapp: myapp.cpp
$(CC) -o $# $< `pkg-config --cflags --libs libpjproject`
clean:
rm -f myapp.o myop
Worked for me, but there was one clue which i stumble over.
This is important and is also described at the bottom of the page i linked. If you notice there are spaces towards the bottom of the file (before $(CC) and rm, these are a single tab, not spaces. This is important, or otherwise make command will fail with "missing separator" error.

Resources