2014-10-11 5 views
8

Ich möchte zwei Alias-Variablen in eine Bibliothek einfügen, so dass der Anwendungscode beide Namen verwenden kann. Aber ich finde, dass es in einer statischen Bibliothek, aber nicht in einer gemeinsam genutzten Bibliothek getan werden kann. Hier ist mein Experiment. Ich habe es auf einem X86 Linux-Rechner mit GCC-Compiler gemacht.Wie haben Sie Alias-Variablen in Shared Libraries?

test.c - der Anwendungscode

#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 - der Bibliothekscode

int myglob = 42; 
extern int myglob_ __attribute__ ((alias("myglob"))); 
int myfunc(int a, int b) 
{ 
    myglob += a; 
    return b + myglob; 
} 

Aufbau und Betrieb mit statischer Bibliothek. Wir können sehen, myglob und myglob_ sind in der Tat Alias.

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 

Erstellen und Ausführen mit einer gemeinsam genutzten Bibliothek. Wir können myglob und myglob_ auf verschiedene Adressen zeigen und sind im Grunde zwei verschiedene Variablen.

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 

Also, warum Alias-Symbole nicht in der gemeinsamen Bibliothek arbeiten? Wie man es repariert? Vielen Dank.

============= Follow-up ===============

Ich habe versucht, eine positionsunabhängige Executable mit „gcc zu bauen -o test test.c -L. -lmy -fPIC ". Damit sind myglob und myglob_ tatsächlich Aliasing mit der gemeinsam genutzten Bibliothek. Dieser Ansatz funktioniert jedoch nicht in dem Hintergrundproblem, das die Frage hervorgebracht hat. Ich liste das Problem und den Grund auf, warum ich es brauche. (Beachten Sie, dass ich F77 gemeinsame Blöcke in meinem Projekt verwenden)

Eine Fortran-Header-Datei

! myf.h 
common /myblock/ myglob 
save myblock 

Init-Routine in Fortran

! initf.f90 
subroutine initf() 
    integer myglob 
    common /myblock/ myglob 
    call initc(myglob) 
end subroutine 

Init-Routine 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 Bibliothekswrapper 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'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"))); 

Anwendung in Fortran

! test.f90 
program main 
    include 'myf.h' 
    call init(); 
    call myfunc(myglob); 
end program 

Erstellen Sie eine gemeinsame Bibliothek libmy.so und es verwenden,

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 

Angenommen wir die Bibliothek wollen tragbar sein, und die Anwendung wird von einem anderen Fortran-Compiler kompiliert mit einem anderen Namen Mangling Konvention (ich benutze gfortran - fno-Unterstreichung, um das nachzuahmen)

// 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 

Irgendwelche Vorschläge? Vielen Dank.

+1

Was ist die verbleibende Frage? Du hast '-fPIC' entdeckt und alles funktioniert wie beabsichtigt. Was ist übrig? –

+0

Wie im folgenden Abschnitt zu sehen, funktioniert es nicht für Fortran/C-Hybridcode. –

+0

Ich dachte, du hast herausgefunden, dass du deine Linker dazu bringen musst, dem Namen Mangling zuzustimmen? –

Antwort

2

Dies geschieht aufgrund von Kopierverlagerungen. Lesen Sie über sie here.

readelf -Wr test | grep myglob 
0000000000601028 0000000600000005 R_X86_64_COPY 0000000000601028 myglob + 0 
0000000000601030 0000000900000005 R_X86_64_COPY 0000000000601030 myglob_ + 0 
+0

Danke. Ich habe festgestellt, wenn ich eine positionsunabhängige ausführbare Datei erstellen, d. H. Mit "gcc -o test test.c-L. -lmy-fPIC", dann auch mit shared-Bibliothek, Alias ​​myglob und myglob_. Dies ist akzeptabel, aber nicht perfekt. Aber als ich diesen Ansatz für das Hintergrundproblem in meinem Projekt anwendete, funktionierte es nicht. Ich werde einen neuen Beitrag geben. –

Verwandte Themen