I want to put two variables with an alias in the library so that the application code can use any name. But I believe that this can be done in a static library, but not in a shared library. Here is my experiment. I did this on an X86 Linux machine with the gcc compiler.
test.c - application code
#include <stdio.h> extern int myfunc(int, int); extern int myglob; extern int myglob_; int main(int argc, const char* argv[]) { printf("&myglob = %p\n", &myglob); printf("&myglob_ = %p\n", &myglob_); myglob = 1234; printf("myglob = %d\n", myglob); printf("myglob_ = %d\n", myglob_); return myfunc(argc, argc); }
my.c - library code
int myglob = 42; extern int myglob_ __attribute__ ((alias("myglob"))); int myfunc(int a, int b) { myglob += a; return b + myglob; }
Build and run using the static library. We can see that myglob and myglob_ are really aliases.
gcc -c my.c ar rsc libmy.a my.o gcc -o test test.c -L. -lmy ./test &myglob = 0x601040 &myglob_ = 0x601040 myglob = 1234 myglob_ = 1234
Build and run with a shared library. We can see that myglob and myglob_ point to different addresses and basically are two different variables.
gcc -fPIC -c my.c gcc -shared -o libmy.so my.o gcc -o test test.c -L. -lmy ./test &myglob = 0x601048 &myglob_ = 0x601050 myglob = 1234 myglob_ = 42
So why don't characters with an alias work in a shared library? How to fix it? Thanks.
============== Follow-up ================
I tried to create a position-independent executable using "gcc -o test test.c -L. -Lmy -fPIC". With this, myglob and myglob_ really have aliases with a shared library. However, this approach does not work in the background problem that raised the question. I list the problem and the reason why I need it. (Note that I have to use F77 common blocks in my project)
Fortran Header File
! myf.h common /myblock/ myglob save myblock
Initialization in Fortran
! initf.f90 subroutine initf() integer myglob common /myblock/ myglob call initc(myglob) end subroutine
Initialization in C
// initc.c #include <stdio.h> extern void initf_(); void init() { initf_(); } extern void init_() __attribute__((alias("init"))); void initc_(int *pmyglob) { printf("&myglob in library = %p\n", pmyglob); }
Fortran library library in C
// my.c #include <stdio.h> extern void myfunc(int *pmyglob) { printf("&myglob in app = %p\n", pmyglob); // May call a Fortran subroutine. That why myfunc() is a wrapper } extern void myfunc_(int *) __attribute__ ((alias("myfunc"))); typedef struct myblock_t_ { int idx; } myblock_t; myblock_t myblock __attribute__((aligned(16))) = {0}; extern myblock_t myblock_ __attribute__((alias("myblock")));
Fortran App
! test.f90 program main include 'myf.h' call init(); call myfunc(myglob); end program
Create a shared library libmy.so and use it
gfortran -fPIC -c initf.f90 gcc -fPIC -c initc.c gcc -fPIC -c my.c gcc -fPIC -shared -o libmy.so initf.o initc.o my.o gfortran -fPIC -o test test.f90 -L. -lmy ./test &myglob in library = 0x601070 &myglob in app = 0x601070
Suppose we want the library to be portable and the application compiled by another Fortran compiler with a different naming convention (I use gfortran -fno-underscoring to mimic this)
// libmy.so is built as same as above ... gfortran -fPIC -fno-underscoring -o test test.f90 -L. -lmy ./test &myglob in library = 0x7fb3c19d9060 &myglob in app = 0x601070
Any suggestions? Thanks.