Cygwin + shared Library



  • Hi,

    zuerst mal sorry, dass ich hier eine Frage zu Cygwin stelle, allerdings denke ich mir, passt es hier besser als in ein anderes Unterforum. Wenn nicht, bitte verschieben.

    Und zwar versuche ich mit "gcc version 3.4.4 (cygming special)" eine shared Library zu erstellen, was auch wunderbar funktioniert. Hier erstmal der Code dazu:

    module.c

    #include <stdio.h>
    
    void
    module_init(void)
    {
    	printf("Module init\n");
    }
    
    void
    module_call(char *text)
    {
    	printf("Module call - %s\n", text);
    	//test();
    }
    
    void
    module_exit(void)
    {
    	printf("Module exit\n");
    }
    

    Makefile module.c

    LIB = ../module.so
    CFLAGS = -Wall -g -I../..
    
    OBJ = $(patsubst %.c,%.o,$(wildcard *.c)) 
    
    .PHONY: all all-before all-after clean clean-custom
    
    all: all-before $(LIB) all-after
    
    clean: clean-custom
    	rm -f $(OBJ) $(LIB)
    
    $(LIB): $(OBJ)
    	gcc $(CFLAGS) -fPIC -Bdynamic -shared -o $(LIB) $(OBJ)
    
    .c.o:
    	gcc ${CFLAGS} -o $@ -c $^
    

    main.c

    #include <stdio.h>
    #include <dlfcn.h>
    
    void
    test(void)
    {
    	printf("Test\n");
    }
    
    int
    main(int argc, char **argv)
    {
    	void *handle;
    	void (*func_init)(void);
    	void (*func_call)(char *text);
    	void (*func_exit)(void);
    
    	printf("Init\n");
    
    	if((handle = dlopen("./module.so", RTLD_LAZY)) == NULL)
    	{
    		printf("Could not load module: %s\n", dlerror());
    		return 0;
    	}
    
    	if((func_init = dlsym(handle, "module_init")) == NULL)
    	{
    		printf("Could not load function: %s\n", dlerror());
    		dlclose(handle);
    		return 0;
    	}
    
    	if((func_call = dlsym(handle, "module_call")) == NULL)
    	{
    		printf("Could not load function: %s\n", dlerror());
    		dlclose(handle);
    		return 0;
    	}
    
    	if((func_exit = dlsym(handle, "module_exit")) == NULL)
    	{
    		printf("Could not load function: %s\n", dlerror());
    		dlclose(handle);
    		return 0;
    	}
    
    	func_init();
    	func_call("Function Call ...");
    	func_exit();
    
    	dlclose(handle);
    
    	printf("Exit\n");
    
    	return 0;
    }
    

    Makefile main.c

    BIN = Test
    CFLAGS = -pipe -Wno-import -Wall -g
    CC = gcc
    LDL = -ldl
    
    ifeq (CYGWIN, $(findstring CYGWIN, $(shell uname -s)))
      LDL =
    endif
    
    OBJ = $(patsubst %.c,%.o,$(wildcard *.c))
    
    .PHONY: all all-before all-after clean clean-custom
    
    all: all-before $(BIN) all-after
    
    clean: clean-custom
    	rm -f $(OBJ) $(BIN)
    
    $(BIN): $(OBJ)
    	@echo "[LD] $@"
    	gcc $(CFLAGS) $(LDL) -Wl,--export-dynamic $(OBJ) -o $(BIN)
    
    .c.o:
    	@echo "[CC] $@"
    	gcc ${CFLAGS} -o $@ -c $^
    

    Wenn ich nun beide Source Files compile und das Programm startet, bekomme ich wie erwartet:

    Init
    Module init
    Module call - Function Call ...
    Module exit
    Exit

    Wenn ich nun aber in der module.c - module_call das ausgeklammerte test(); wieder aktiviere, um damit auf die Funktion void test(void) aus main.c zuzugreifen, funktioniert auch dieses unter Unix (wobei man dafür aber das Compiler Flag -ldl in der Makefile gesetzt haben sollte/muss), aber eben nicht unter Cygwin (dort ist das Flag -ldl nicht bekannt).
    Bei Cygwin bekomme ich einen Linkerfehler, dass eben die test() Funktion undefiniert ist.

    gcc -Wall -g -I../.. -o module.o -c module.c
    module.c: In function module_call': module.c:13: warning: implicit declaration of functiontest'
    gcc -Wall -g -I../.. -fPIC -Bdynamic -shared -o ../module.so module.o
    module.o: In function module_call': /xModule/mod/module.c:13: undefined reference to_test'
    collect2: ld returned 1 exit status
    make: *** [../module.so] Error 1

    Ich habe zig Stunden im Netz nach der Lösung gesucht und irgendwie das Gefühl bekommen, dass es irgendwie funktionieren könnte, allerdings habe ich nirgendwo eine konkrete Lösung gefunden. Vielleicht hat hier jemand einen Tipp, was ich mal probieren sollte oder einen Hinweis auf die Lösung. Das FAQ zu *.so konnte mir auch nicht weiterhelfen.

    Im Moment benutze ich noch Funktionspointer, heißt ich übergebe der module_init ein Pointer auf die Funktion test() aus main.c, was aber auch nicht die Lösung sein kann/sollte.

    Wäre klasse, wenn da jemand eine Idee hätte.

    Schonmal vielen Dank im voraus.


Anmelden zum Antworten