Chcę umieścić dwie aliasingowane zmienne w bibliotece, aby kod aplikacji mógł używać obu nazw. Ale uważam, że można to zrobić w bibliotece statycznej, ale nie w bibliotece współdzielonej. Oto mój eksperyment. Zrobiłem to na maszynie X86 Linux z kompilatorem gcc.Jak uzyskać aliasing zmiennych w bibliotekach współdzielonych?
test.c - kod aplikacji
#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 - kod biblioteki
int myglob = 42;
extern int myglob_ __attribute__ ((alias("myglob")));
int myfunc(int a, int b)
{
myglob += a;
return b + myglob;
}
budowy i uruchomienia z biblioteką statyczną. Możemy zobaczyć, że myglob i myglob_ są rzeczywiście aliasingowane.
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
Tworzenie i uruchamianie z udostępnioną biblioteką. Możemy zobaczyć, że myglob i myglob_ wskazują na różne adresy i zasadniczo są to dwie różne zmienne.
Dlaczego symbole alikwotowe nie działają w bibliotece współdzielonej? Jak to naprawić? Dzięki.
============= Kontynuacja ===============
Próbowałem zbudować wykonywalny niezależne od pozycji przy użyciu „gcc -o test test.c -L. -lmy -fPIC ". Dzięki temu, myglob i myglob_ są rzeczywiście aliasowane z biblioteką współdzieloną. Jednak takie podejście nie działa w tle problemu, który wywołał pytanie. Wymieniam problem i powód, dla którego go potrzebuję. (Zauważ, że muszę używać F77 wspólne bloki w moim projekcie) Plik
Fortran nagłówek
! myf.h
common /myblock/ myglob
save myblock
Init rutyna w Fortran
! initf.f90
subroutine initf()
integer myglob
common /myblock/ myglob
call initc(myglob)
end subroutine
Init rutyna w 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); }
Opakowanie biblioteki Fortran w C
// my.c
#include <stdio.h>
extern void myfunc(int *pmyglob)
{
printf("&myglob in app = %p\n", pmyglob);
// May call a Fortran subroutine. That's 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")));
Zastosowanie w Fortran
! test.f90
program main
include 'myf.h'
call init();
call myfunc(myglob);
end program
Budowanie wspólnej libmy.so biblioteki i używać go
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
Załóżmy, że chcemy biblioteka być przenośne, a aplikacja jest skompilowany przez innego kompilatora Fortran z inną nazwą - konwencja mangling (używam gfortran - podświetlając to naśladując)
// 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
Jakieś sugestie? Dzięki.
Jakie jest pozostałe pytanie? Odkryłeś '-fPIC' i wszystko działa zgodnie z przeznaczeniem. Co zostało? –
Jak widać w sekcji kontrolnej, to nie działa dla hybrydowego kodu Fortran/C. –
Pomyślałem, że udało ci się przekonać twoich linkerów, żeby zgodzili się na mylące nazwy? –