I have an application that runs fine on Ubuntu but immediately exit at startup, WITHOUT ANY ERRORS, on Windows.
It seems that main() function is not entered.
Application has been compiled without errors and it uses SDL_image.h. When (in the same application) the code that uses SDL Image was not present the application was running fine.
In the .exe directory there are all the needed dlls, SDL2.dll, libjpeg-9.dll, libpng16-16.dll, libtiff-5.dll, libwebp-7.dll, SDL2_image.dll and zlib1.dll.
IMG_Init() is called before any other image functions in this way:
(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG)
and, as I said before, tha application runs without problems on Ubuntu.
This is a reproducible example.
This code works:
makefile
CC = gcc -fno-pie -no-pie -m32
CFLAGS = -IC:/sdl2/include -O0 -ggdb
LIBS = -LC:/sdl2/lib/x86 -lSDL2main -lSDL2
all:
$(CC) $(CFLAGS) main.c $(LIBS) -o application.exe
main.c
#include <stdio.h>
#include "SDL.h"
int main(int argc, char **argv)
{
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
{
SDL_Log("SDL fails to initialize video subsystem!\n%s", SDL_GetError());
return -1;
}
else
printf("SDL Video was initialized fine!\n");
return 0;
}
This code, where I use SDL Image library, doesn't do nothing, no errors, immediately exits:
makefile
CC = gcc -fno-pie -no-pie -m32
CFLAGS = -IC:/sdl2/include -IC:/sdl2_image/include -O0 -ggdb
LIBS = -LC:/sdl2/lib/x86 -LC:/sdl2_image/lib/x86 -lSDL2main -lSDL2 -lSDL2_image
all:
$(CC) $(CFLAGS) main.c $(LIBS) -o application.exe
main.c
#include <stdio.h>
#include "SDL.h"
#include "SDL_image.h"
int main(int argc, char **argv)
{
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
{
SDL_Log("SDL fails to initialize video subsystem!\n%s", SDL_GetError());
return -1;
}
else
printf("SDL Video was initialized fine!\n");
if((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG)
{
SDL_Log("SDL fails to initialize image handler!\n%s", IMG_GetError());
return -1;
}
else
printf("SDL Image was initialized fine!\n");
return 0;
}
As I said before, it seems that the problem is the windows library (or the environment) and this is why I didn't add a reproducible code before
After 2 days I found a solution.
First of all (but it isn't my problem) the SDL Image library is not so "smart" so it is important that SDL2_image.dll library and the used ones from libjpeg-9.dll, libpng16-16.dll, libtiff-5.dll, libwebp-7.dll and zlib1.dll are present. You'll not receive any error if one of needed library is missing.
I had a problem in my environment, on this machine I use Visual Studio and Eclipse. I made a mistake and my makefile pointed to Visual Studio SDL libraries and not to MinGW ones.
I don't know why but the first reproducible example works fine also with this mistake (and without -lmingw32), so it pointed me out of the correct way.
I did this change on makefile and now it works:
CFLAGS = -IC:/sdl2_mingw/i686-w64-mingw32/include/SDL2 -IC:/sdl2_image_mingw/i686-w64-mingw32/include/SDL2 -O0 -ggdb
LIBS = -lmingw32 -LC:/sdl2_mingw/i686-w64-mingw32/lib -LC:/sdl2_image_mingw/i686-w64-mingw32/lib -lSDL2main -lSDL2 -lSDL2_image
Related
Im working with C on MacOS, when i compile the program by myself with
gcc main.c -o prog $(sdl2-config --cflags --libs)
It works fine, but when i try to make it work with a makefile i keep facing this error
gcc -o main.o -c main.c prog
clang: warning: prog: 'linker' input unused [-Wunused-command-line-argument]
main.c:1:10: fatal error: 'SDL.h' file not found
#include <SDL.h>
There is my code
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdbool.h>
int main (int argc, char **argv)
{
SDL_Window *window = NULL;
if ( SDL_Init(SDL_INIT_VIDEO) != 0)
{
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
window = SDL_CreateWindow("Bomberman", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_MINIMIZED);
if (window == NULL)
{
SDL_Log("Unable to create window: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
bool window_open = true;
while (window_open)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
window_open = false;
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
And here is my makefile
main.o: main.c
gcc -o main.o -c main.c prog $(sdl2-config --cflags --libs)
Well, look at the command you ran from the compile line:
gcc main.c -o prog $(sdl2-config --cflags --libs)
This builds an output prog from the source file. And compare it to your recipe:
gcc -o main.o -c main.c prog $(sdl2-config --cflags --libs)
^^^^^^^^^^^^
They aren't the same, so clearly you won't get the same result. Plus you've told make you're trying to build the output file main.o, not prog as your command line version does.
First, remove the extra stuff and fix the target.
Second, $ is special to make (it introduces a make variable). So in your makefile recipe $(sdl2-config --cflags --libs) is actually expanding a very oddly-named make variable.
You want this:
prog: main.c
gcc main.c -o prog $$(sdl2-config --cflags --libs)
Make already defines a builtin rule for building .o files from .c files with the same base name. You should use that and the standard FLAGS variables. So you end up wanting something like:
CFLAGS = $$(sdl2-flags --cflags)
LDLIBS = $$(sdl2-flags --libs)
With just that, you can type make main.o to compile main.o and make main to build an executable main from main.o (if it exists) or main.c (if there's no main.o already)
If you want to build prog, you can add a rule
prog: main.o
$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS)
I am forced to link two version of the same third party dynamic library (Linux .so, C language) into the same executable to support old and new functionality in the same process. Having two executables or remote services are undesirable.
I made the assumption that this must be a doable task. I tried to experiment with the naive approach of creating 2 proxy dynamic libraries each linked against one of the real libraries and have function renamed.
Unfortunately, this attempt failed – both new functions call the same target function.
I still want to believe that the problem is in the lack of my knowledge as there are plenty of compiler and linker ( gcc and ld) options.
I will appreciate any help. I also look forward to using dlopen/dlsym, but first want to check if the original approach can work.
Here is the sample code
/* ./old/b.c */
#include <stdio.h>
int b (int i)
{
printf("module OLD %d\n",i);
return 0;
}
/* ./old/Makefile */
libold.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./new/b.c */
#include <stdio.h>
int b (int i)
{
printf("module new %d\n",i);
return 0;
}
/* ./new/Makefile */
libnew.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./a1.c */
#include <stdio.h>
int b(int);
void call_new(void)
{
printf("will call new 1\n");
b(1);
printf("called new 1\n");
}
/* ./a2.c */
#include <stdio.h>
int b(int);
void call_old(void)
{
printf("will call old 2\n");
b(2);
printf("called old 2\n");
}
/* ./main.c */
#include <stdio.h>
int call_new(void);
int call_old(void);
int main()
{
call_new();
call_old();
return 0;
}
/* ./Makefile */
.PHONY: DEPSNEW DEPSOLD clean
main: liba1.so liba2.so main.c
gcc -c main.c
gcc -o main main.o -rdynamic -Wl,-rpath=new -Wl,-rpath=old -L . -la1 -la2
DEPSNEW:
make -C new
DEPSOLD:
make -C old
liba1.so: DEPSNEW a1.c
gcc -c -fpic a1.c
gcc -shared a1.o -L new -lnew -o liba1.so
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -o liba2.so
clean:
find -name "*.so" -o -name "*.o" -o -name main | xargs -r rm
/* ./run.sh */
#/bin/sh
LD_LIBRARY_PATH=new:old:. main
The result is not that I want - function from "new" library is called twice
will call new 1
module new 1
called new 1
will call old 2
module new 2
called old 2
In this case, you can not control the automatic loading of the dynamic library in order to assure which library will be loaded for the depending libraries. What you can do, is to use one of the libraries (the new one) for the dynamic linker and to link the second library manually as follows:
Add function to dynamically load and link the function from the library.
a2.c
#include <stdio.h>
#include <dlfcn.h>
static int (*old_b)(int);
void init_old(void) {
void* lib=dlopen("./old/libold.so", RTLD_LOCAL | RTLD_LAZY);
old_b=dlsym(lib,"b");
}
void call_old(void)
{
printf("will call old 2\n");
old_b(2);
printf("called old 2\n");
}
call the initialization function
main.c
#include <stdio.h>
void init_old(void);
int call_new(void);
int call_old(void);
int main()
{
init_old();
call_new();
call_old();
return 0;
}
Modify the linker options to add the dynamic loading library -ldl
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -ldl -o liba2.so
After this modification
~$ ./run.sh
will call new 1
module new 1
called new 1
will call old 2
module OLD 2
called old 2
I'm trying to debug claws-mail notification plugin, I have code like this:
#include "notification_indicator.h"
#include "notification_prefs.h"
#include "notification_core.h"
#include "folder.h"
#include "common/utils.h"
#include <messaging-menu.h>
#include <unity.h>
#define CLAWS_DESKTOP_FILE "claws-mail.desktop"
#include <stdio.h>
void main(void)
{
GList *cur_mb;
gint total_message_count;
total_message_count = 0;
/* check accounts for new/unread counts */
for(cur_mb = folder_get_list(); cur_mb; cur_mb = cur_mb->next) {
Folder *folder = cur_mb->data;
NotificationMsgCount count;
if(!folder->name) {
printf("Notification plugin: Warning: Ignoring unnamed mailbox in indicator applet\n");
continue;
}
gchar *id = folder->name;
notification_core_get_msg_count_of_foldername(folder->name, &count);
printf("%s: %d\n", folder->name, count.unread_msgs);
}
}
and I'm compiling it with this command:
gcc -I/home/kuba/Pobrane/claws-mail-3.13.2/src/
-I/usr/include/gtk-2.0/
-I/usr/include/cairo/
-I/usr/include/pango-1.0
-I/usr/lib/i386-linux-gnu/gtk-2.0/include/
-I/usr/include/gdk-pixbuf-2.0/
-I/usr/include/atk-1.0/
-I/home/kuba/Pobrane/claws-mail-3.13.2/src/common
-I/home/kuba/Pobrane/claws-mail-3.13.2/src/gtk
-I/usr/include/messaging-menu/
-I/usr/include/unity/unity/
-I/usr/include/dee-1.0/
-I/usr/include/libdbusmenu-glib-0.4/
-c `pkg-config --cflags glib-2.0` test.c
but gcc create object file test.o instead of a.out how can I create executable file? I'm running this on Xubuntu.
Remove the -c option from the commandline (which generates the object file instead of executable).
From man gcc:
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form
of an object file for each source file.
Examples:
To generate an object file (`.o' file):
gcc -c test.c
To generate an executable:
gcc test.c -o test
(if you omit the -o test, it'd generate a.out as executable by convention).
I have really simple program that checks if the word that user types is palindrome: ( I know that this program could be written much better but let's leave that aside for now )
I have to use readline function to get users input or create my own, but because I don't have enough knowledge to create my own I'm using readline.
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
int IsPalindrome(char* niz)
{
int y=0;
int n=0;
int i;
for(i=1;i<strlen(niz)/2+1;i++)
{
if(niz[i-1]==niz[strlen(niz)-i]){
y++;
}
else{
n++;
}
}
if(n>0){
return 0;
}
else{
return 1;
}
}
int main()
{
char *inpt;
inpt = readline("enter text: ");
if(IsPalindrome(inpt)==1)
{
printf("\nIs palindrome\n");
}
else{
printf("\nNot palindrome\n");
}
return 0;
}
I'm using Code::Blocks and if I click on "build and run" I get following error:
Undefined reference to 'readline'
I have to compile and then run my program from terminal with makefile and this is where I'm lost. I just recently started using Ubuntu so I don't really know much about it and how it works.
Now I have to compile my program with makefile ( all in run ). This is makefile that we can use ( I'm at university and we got this as help ) we just have to change some data ( name of the program, add some flags ):
GCC=gcc
CFLAGS=-c -g
LFLAGS=-lreadline
EXE=main
all: ${EXE}.o
${GCC} ${LFLAGS} ${EXE}.o -o ${EXE}
${EXE}.o: ${EXE}.c
${GCC} ${CFLAGS} ${EXE}.c
clean:
rm -rf *.o
rm -rf ${EXE}
Now because I'm using readline function I added flag -lreadline and added name of my program to EXE=main ( my program is called main.c ) but if I run makefile ( make all ) I get following error:
make all
gcc -lreadline main.o -o main
main.o: In function `main':
/home/yack/Desktop/NPO/Palindrom/Palindrom/main.c:67: undefined reference to `readline'
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target 'all' failed
make: *** [all] Error 1
I installed Readline-6.3 and I was reading on the internet that I have to somehow link readline to tell compiler about it or something but looks like adding -lreadline flag is not enough.
Yesterday I found temporary fix so that I could test if my program works with this command:
gcc main.c -L/usr/local/lib -I/usr/local/include -lreadline -c -g
With this command I managed to create executable file and test if my program works, but today even that doesn't work anymore.
NOTE:
I have to compile my program from makefile, the last command in terminal was just to check if my program works since my makefile didn't work.
What am I doing wrong ?
The order of arguments passed to GCC (and the linker) is relevant.
Your Makefile should have the use of libreadline come before where you actually link libreadline with LFLAGS, like so:
GCC=gcc
CFLAGS=-c -g
LFLAGS=-lreadline
EXE=main
all: ${EXE}.o
${GCC} ${EXE}.o -o ${EXE} ${LFLAGS}
${EXE}.o: ${EXE}.c
${GCC} ${CFLAGS} ${EXE}.c
clean:
rm -rf *.o
rm -rf ${EXE}
In your "temporary fix" you fixed the ordering, and that is why it worked for you.
EDIT found an issue, but it still needs to be solved it should be below in answers
My task is to write app based on existing files. test.c(main) randapi.c randapi.h(2 functions in here) and initapi.c(one function). "how can You use dynamic library as dynamic loaded library. Using eg9 (where i made a dynamic library and it worked fine) write app where this libraries will be attached dynamic"
here is my try with a makefile but terminal says that :failed to open when i come to run file using ./program
i have tried also version without attaching initapi.c but then it says initRand is unknown besides that make file clearly attached it
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#define ITERATIONS 1000000L
int main(int argc, char** argv)
{
long i;
long isum;
float fsum;
void *lib;
lib=dlopen("librandapi.so", RTLD_LAZY);
if (!lib)
{
printf("failed to open");
exit(1);
}
int (*getRand)(int);
float (*getSRand)();
void (*initRand)();
getRand=dlsym(lib,"getRand");
getSRand=dlsym(lib,"getSRand");
initRand=dlsym(lib,"initRand");
initRand();
isum = 0L;
for (i = 0 ; i < ITERATIONS ; i++) {
isum += ((*getRand)(10));
}
printf( "getRand() Average %d\n", (int)(isum / ITERATIONS) );
fsum = 0.0;
for (i = 0 ; i < ITERATIONS ; i++) {
fsum += ((*getSRand)());
}
printf( "getSRand() Average %f\n", (fsum / (float)ITERATIONS) );
dlclose(lib);
return 0;
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
makefile
zad9: test.c
gcc -Wall -o zad9 test.c -ldl
librandapi.so: randapi.o initapi.o
gcc -shared -o librandapi.so randapi.o initapi.o
randapi.o: randapi.c randapi.h
gcc -c -Wall -fPIC randapi.c
initapi.o: initapi.c
gcc -c -Wall -fPIC initapi.c
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
zad9: test.c initapi.c
gcc -Wall -o zad9 test.c initapi.c -ldl
librandapi.so: randapi.o initapi.o
gcc -shared -o librandapi.so randapi.o
randapi.o: randapi.c randapi.h
gcc -c -Wall -fPIC randapi.c
Look at this line in man 3 dlopen:
If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) path‐name. Otherwise, the dynamic linker searches for the object as follows (see ld.so(8) for further details):
(and then a buch of rules that do not include the current directory nor the one where the executable is).
My guess is that you are copying librandapi.so to the current directory and that's why dlopen() cannot find it.
If that's the case, the solution is easy:
lib=dlopen("./librandapi.so", RTLD_LAZY);