I've created a DLL on Linux (CentOS 6.7) with MXE (a MinGW cross-compile environment on Linux) static toolchain. If it does not link with glib, everything looks fine. However, if it links with glib, dumpbin /exports libtest.dll only show the symbols in glib (prefixed with g_, eg g_int_equal).
For example, the small test c code
#include <glib.h>
int global_func(void)
{
int c = 0xff;
return c;
}
int local_func(int ini)
{
int a = 1, b = 2;
g_int_equal(&a, &b);
return ini + 1;
}
The command to build the DLL:
x86_64-w64-mingw32.static-gcc -c -o test.o test.c -I/home/STools/mxe/usr/x86_64-w64-mingw32.static/include/glib-2.0 -I/home/STools/mxe/usr/x86_64-w64-mingw32.static/lib/glib-2.0/include
x86_64-w64-mingw32.static-g++ -Wl,-soname,libtest.dll -Wl,--version-script=test.version -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m64 -g -shared -o libtest.dll test.o -lglib-2.0 -lintl -liconv -lwinmm -lws2_32 -liphlpapi -lole32
The version script, test.version:
FOO {
global:
global_func;
local: *; # hide everything else
};
Then I dump the exported symbols in libtest.dll in Windows with:
dumpbin /exports libtest.dll
It shows a lot of functions in glib, but no "global_func".
Glib here is static library. I also tried the shared toolchain, x86_64-w64-mingw32.shared-g++. With static Glib, the result is the same. So, when I try to find some function in the DLL with GetProcAddress, it fails.
Anything wrong?
I've also downloaded the DLL version of Glib from gnome website. Now the exported functions are right.
Related
I would like to debug shared library in Visual C++ Linux Development. Debugging executable file works well, but the breakpoint does not hit for shared library. How can I fix up?
Attached file is visual studio solution including .c and Makefile.
Example is very simple.
open shared library
read pointer of function in shared library
call the function.
Program works well. But Debugging shared library does not works. The breakpoint in main.c hits but the breakpoint in com.c does NOT hit.
/* main.c */
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char** argv)
{
void* dl_handle;
dl_handle = dlopen("../so/libcom.so.1", RTLD_LAZY);
if (!dl_handle) {
printf(" error : %s \n", dlerror());
return 0;
}
printf(" now call minicommon.h's function.. that is < void print_n(int n) >...\n");
void(*pFunc)(int);
pFunc = dlsym(dl_handle, "print_n");
(*pFunc)(18);
return 0;
}
/* com.c */
#include <stdio.h>
void print_n(int a)
{
printf("SO - print: [%d]\n", a);
}
/* Makefile for main.c */
all: main
main: main.o
gcc -W -Wall -gdwarf-2 -o main ../so/libcom.so.1 main.o -ldl
main.o: main.c
gcc -Wall -c -gdwarf-2 -o main.o main.c
clean:
rm -rf *.o main
/* Makefile for com.c */
all: libcom.so.1
libcom.so.1: com.o
gcc -shared -gdwarf-2 -o libcom.so.1 com.o
com.o: com.c
gcc -Wall -c -gdwarf-2 -o com.o com.c -fPIC
clean:
rm -rf *.o libcom.so.1
Before shared library is opened, can I debug it?
Environment
- Window 10
- CentOS 7 in VirtualBox
- Visual Studio 2015 update 3
- Visual C++ for linux Development 1.0.7
To be able to debug any binary (which includes shared libraries) you need the debugging symbols being available, either compiled into the binary itself, or as a separate file.
In most Linux distributions you can install the debugging symbols as separate package; Ubuntu for instance names these packages <packagename>-dbg. Check if these are available in your development environment, too.
I was trying this on my 64 bit ubuntu:
First I've got a simple program
$ cat test.c
int f(int x){
int i=(x/42);
return i;
}
int main(){
return 0;
}
Then I manually specify how it's linked:
$ gcc test.c -nostdlib /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o
I got some errors:
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’中:
(.text+0x12):unresolved reference to ‘__libc_csu_fini’
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’:
(.text+0x19): unresolved reference to ‘__libc_csu_init’
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’:
(.text+0x25): unresolved reference to ‘__libc_start_main’
collect2: error: ld returned 1 exit status
I was trying to see how gcc deals with all necessary object files and try to do it manually. How to fix it? Thanks.
How to fix it?
You are missing libc symbols, so you need to link libc:
gcc test.c -nostdlib /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o -lc
Bear in mind that if you really want to link something "manually", you will do it with ld, not gcc
I can't find a way to compile the following test code under Linux (part of a program developed for Mac)
#include<GL/glui.h>
void test(){
const char *name
GLint uni_loc,x,y ;
GLuint id;
glVertex2i( x, y);
uni_loc = ::glGetUniformLocation(id, name) ;
}
I tried to compile it with:
g++ -c test.cpp -lglut -lGL -lGLU
g++ -c -lglut -lGL -lGLU test.cpp
I get a linker error for the glGetUniformLocation function:
'::glGetUniformLocation' has not been declared
But don't know how to resolve it. I have no knowledge of openGl and get completely lost between the different implementations. I found the definition of the function in
/usr/include/GL/gl_mangle.h
/usr/include/GL/glew.h
/usr/include/GL/glext.h
Could it be that I have the wrong version of GL?
I have the following packages installed:
freeglut3 freeglut3-dev libglew1.5 libglew1.5-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev mesa-common-dev
and gcc version 4.7.2 (Debian 4.7.2-5).
A portable way to get the functions defined in an extension is to use an extension wrapper like GLEW. A less robust way is to define GL_GLEXT_PROTOTYPES before including "GL/gl.h" and "GL/glext.h".
I successfully ran sudo apt-get install libncurses5-dev
Within my Eclipse window I then try to build the following HelloWord.cpp program:
#include <ncurses.h>
int main()
{
initscr(); /* Start curses mode */
printw("Hello World !!!"); /* Print Hello World */
refresh(); /* Print it on to the real screen */
getch(); /* Wait for user input */
endwin(); /* End curses mode */
return 0;
}
I get the following error:
Invoking: GCC C++ Linker
g++ -m32 -lncurses -L/opt/lib -o "Test_V" ./src/curseTest.o ./src/trajectory.o ./src/xJus-epos.o -lEposCmd
/usr/bin/ld: cannot find -lncurses
collect2: error: ld returned 1 exit status
make: *** [Test_V] Error 1
It looks like the compiler is searching for the ncurses library and can't find it? I checked /usr/lib and the library does not exist there so do I need to manually link the ncurses library there - I thought the get-apt installer would automatically do this?
g++ HelloWorld.cpp -lncurses -o HelloWolrd
If you have a 32-bit machine, gcc compile m32 auto. If you have a 64-bit machine and you want to compile 32bits you
Your arguments are not in the correct order. You must specify all source files first and then linker search directories before specifying the libraries to link with. Your command should be like this:
g++ HelloWorld.o -L/opt/lib -lncurses -o HelloWorld
Taken from comment by #ChrisDodd:
Your options are in the wrong order -- -L must be BEFORE -l and both must be after all .o
I'm trying to compile a simple JNI application on an embedded Linux platform (a GuruPlug computer), but for some reason it's not linking to libc properly. The Java program I'm compiling is called Test.java:
public class Test {
static {
System.loadLibrary("Test");
}
public static void main(String[] args) {
new Test().printMessage();
}
public native void printMessage();
}
The implementation of printMessage() is in Test.c:
#include <jni.h>
#include <stdio.h>
#include "Test.h"
JNIEXPORT void JNICALL Java_Test_printMessage(JNIEnv *env, jobject obj)
{
printf("Message 123...\n");
}
I'm compiling Test.c with the following command on a bash shell:
gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so
When I run the above command, I get the error message "R_ARM_TLS_LE32 relocation not permitted in shared object". The full error message is:
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabi/4.4.5/../../../libc.a(dl-tsd.o)(.text+0x18): R_ARM_TLS_LE32 relocation not permitted in shared object
Despite the error message, the JNI .so file is still written by the compiler, but running the Java application gives the following error message:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/jni/libTest.so: /usr/lib/jni/libTest.so: unexpected reloc type 0x03
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
at java.lang.Runtime.loadLibrary0(Runtime.java:840)
at java.lang.System.loadLibrary(System.java:1047)
at Test.<clinit>(Test.java:3)
Could not find the main class: Test. Program will exit.
Does anybody have any idea how to go about fixing this? Admittedly, the above code is a toy example, but I need to get a real JNI library compiling on this platform, and the real JNI library depends on libc. I can't seem to solve this basic issue of linking libc with a JNI library. Any suggestions would be greatly appreciated.
Thanks!
gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so
There are several problems with the command line above:
the -shared and -static flags are mutually exclusive, and the second overrides the first
when linking shared libraries, you want -fPIC on most architectures
the -lc is in the wrong place (should follow your sources, not precede them), and is not necessary anyway: gcc will add it automatically
you don't strictly need the -soname either; it's just useless clutter
The correct command then is:
gcc -g -shared -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux \
Test.c -o libTest.so