SORU
4 AĞUSTOS 2011, PERŞEMBE


Nasıl statik olarak bağlı kütüphaneler arasında sembol çakışmaları ile başa çıkmak için?

Bir kütüphanesi en önemli kurallar ve en iyi uygulamalar biri, tüm semboller koyuyor Kütüphanesi özel bir ad alanına kütüphane. C bu kolay, namespace anahtar dolayı yapar. İçinde C her zamanki yaklaşımı bazı kütüphane belirli bir önek ile tanımlayıcıları önek.

C standart kurallar bunlar üzerinde bazı kısıtlamalar koymak (kasa derleme için): C compiler sadece ilk bakabilir Tanımlayıcı foobar2k_eggs foobar2k_spam 8 karakter olarak yorumlanabilir tanımlayıcılar geçerli – keyfi uzun tanımlayıcıları ancak her modern derleyici sağlar, günümüzde çok (21. yüzyıl) bu rahatsız etmemeliyiz.

Ama eğer biri olamaz bazı kütüphaneler karşı karşıya iseniz sembol isimleri / idenfiers neyi değiştirir? Belki de sahip statik ikili ve başlıkları ya da sadece istemiyorum, ya da kendini yeniden ayarlamak için izin verilmez.

CEVAP
4 AĞUSTOS 2011, PERŞEMBE


En azından işin içindestatikkütüphaneler çevresinde oldukça rahat çalışabilirsiniz.

Kütüphaneler bu başlıkları düşününfoovebar. Bu yazının hatırı için de kaynak dosyaları vereceğim

ex01//örnek foo.h

int spam(void);
double eggs(void);

ex01//örnek foo.c (bu opak/değil mevcut olabilir)

int the_spams;
double the_eggs;

int spam()
{
    return the_spams  ;
}

double eggs()
{
    return the_eggs--;
}

örnek/ex01/bar.h

int spam(int new_spams);
double eggs(double new_eggs);

örnekler/ex01/bar.c (bu opak/değil mevcut olabilir)

int the_spams;
double the_eggs;

int spam(int new_spams)
{
    int old_spams = the_spams;
    the_spams = new_spams;
    return old_spams;
}

double eggs(double new_eggs)
{
    double old_eggs = the_eggs;
    the_eggs = new_eggs;
    return old_eggs;
}

Program foobar bu kullanmak istiyoruz

örnek/ex01/falanca.c

#include <stdio.h>

#include "foo.h"
#include "bar.h"

int main()
{
    const int    new_bar_spam = 3;
    const double new_bar_eggs = 5.0f;

    printf("foo: spam = %d, eggs = %f\n", spam(), eggs() );
    printf("bar: old spam = %d, new spam = %d ; old eggs = %f, new eggs = %f\n", 
            spam(new_bar_spam), new_bar_spam, 
            eggs(new_bar_eggs), new_bar_eggs );

    return 0;
}

Tek sorun hemen belli olur: C aşırı bilmiyor. İki kere iki işlevi var aynı isim ama farklı imza. Bir şekilde bunları ayırt etmek lazım. Neyse, bakalım ne derleyici bu konuda şöyle der:

example/ex01/ $ make
cc    -c -o foobar.o foobar.c
In file included from foobar.c:4:
bar.h:1: error: conflicting types for ‘spam’
foo.h:1: note: previous declaration of ‘spam’ was here
bar.h:2: error: conflicting types for ‘eggs’
foo.h:2: note: previous declaration of ‘eggs’ was here
foobar.c: In function ‘main’:
foobar.c:11: error: too few arguments to function ‘spam’
foobar.c:11: error: too few arguments to function ‘eggs’
make: *** [foobar.o] Error 1

Tamam, bu zaten bildiğimiz şeyi bize anlattı, sürpriz, ya da en azından şüpheliydi.

Yani biz bir şekilde orijinal kütüphaneler değiştirmeden bu identifer çarpışma çözebilir' kaynak kodu veya başlıklar? Aslında yapabiliriz.

İlk defa derleme sorunları gidermek sağlar. Bunun için bir başlık içerir biz surround tüm semboller kütüphane tarafından verilen önek #define ön işlemci direktifleri takımı. Sıcacık ve rahat olan bu kapsayıcı başlık yapıyoruz daha sonra, ama sadece gösteri uğruna neler olduğunu aynen bunu yapıyordufalanca.ckaynak dosya:

örnek/ex02/falanca.c

#include <stdio.h>

#define spam foo_spam
#define eggs foo_eggs
#  include "foo.h"
#undef spam
#undef eggs

#define spam bar_spam
#define eggs bar_eggs
#  include "bar.h"
#undef spam
#undef eggs

int main()
{
    const int    new_bar_spam = 3;
    const double new_bar_eggs = 5.0f;

    printf("foo: spam = %d, eggs = %f\n", foo_spam(), foo_eggs() );
    printf("bar: old spam = %d, new spam = %d ; old eggs = %f, new eggs = %f\n", 
           bar_spam(new_bar_spam), new_bar_spam, 
           bar_eggs(new_bar_eggs), new_bar_eggs );

    return 0;
}

Şimdi Eğer biz bu derleme...

example/ex02/ $ make
cc    -c -o foobar.o foobar.c
cc   foobar.o foo.o bar.o   -o foobar
bar.o: In function `spam':
bar.c:(.text 0x0): multiple definition of `spam'
foo.o:foo.c:(.text 0x0): first defined here
bar.o: In function `eggs':
bar.c:(.text 0x1e): multiple definition of `eggs'
foo.o:foo.c:(.text 0x19): first defined here
foobar.o: In function `main':
foobar.c:(.text 0x1e): undefined reference to `foo_eggs'
foobar.c:(.text 0x28): undefined reference to `foo_spam'
foobar.c:(.text 0x4d): undefined reference to `bar_eggs'
foobar.c:(.text 0x5c): undefined reference to `bar_spam'
collect2: ld returned 1 exit status
make: *** [foobar] Error 1

... önce kötü şeyler var gibi görünüyor. Ama yakından bakın: Aslında derleme aşaması gayet iyi gitti. Şimdi semboller çarpışması olduğunu şikayetçi olan linker. ve bizi bu durum konumu (kaynak dosya ve satır) söyler. Ve gördüğünüz gibi bu semboller öneksiz.

Bu simge tablolara bir göz atalımnmprogramı:

example/ex02/ $ nm foo.o
0000000000000019 T eggs
0000000000000000 T spam
0000000000000008 C the_eggs
0000000000000004 C the_spams

example/ex02/ $ nm bar.o
0000000000000019 T eggs
0000000000000000 T spam
0000000000000008 C the_eggs
0000000000000004 C the_spams

Şimdi bazı opak ikili bu semboller önek için egzersiz ile itiraz ediyoruz. Evet, biliyorum bu örnek ders kaynakları var ve bu değişebilir. Ama şimdilik, sadece farz sadece o vardosya ya da bir.bir(aslında başka bir şey değildir).

objcopykurtarma için

Bir aracı particularily bizim için ilginçtirobjcopy

objcopy yerinde işletim sanki kullanmamız için geçici dosyalar üzerinde çalışır. Kimse yok seçenek/operasyonu--prefix-sembollerne 3 tahmin hakkı var.

Hadi inatçı kütüphaneleri üzerine: bu adam atmak bu kadar

example/ex03/ $ objcopy --prefix-symbols=foo_ foo.o
example/ex03/ $ objcopy --prefix-symbols=bar_ bar.o

nmgösterir Bu iş gibi görünüyordu bize:

example/ex03/ $ nm foo.o
0000000000000019 T foo_eggs
0000000000000000 T foo_spam
0000000000000008 C foo_the_eggs
0000000000000004 C foo_the_spams

example/ex03/ $ nm bar.o
000000000000001e T bar_eggs
0000000000000000 T bar_spam
0000000000000008 C bar_the_eggs
0000000000000004 C bar_the_spams

Bu olayı bağlamayı deneyin sağlar:

example/ex03/ $ make
cc   foobar.o foo.o bar.o   -o foobar

Ve gerçekten de işe yaradı:

example/ex03/ $ ./foobar 
foo: spam = 0, eggs = 0.000000
bar: old spam = 0, new spam = 3 ; old eggs = 0.000000, new eggs = 5.000000

Şimdi otomatik olarak ayıklayan araç/komut dosyası uygulamak için okuyucu için bir alıştırma olarak bırakıyorum bir kütüphane sembolleri kullanaraknmyazar sarıcı yapısı . dosya Başlığı

/* wrapper header wrapper_foo.h for foo.h */
#define spam foo_spam
#define eggs foo_eggs
/* ... */
#include <foo.h>
#undef spam
#undef eggs
/* ... */

ve Sembol statik kütüphane nesne dosyalarını kullanarak önek geçerlidirobjcopy.

Ne paylaşılan kitaplıkları hakkında?

Prensip olarak aynı paylaşılan kitaplıkları ile yapılabilir. Ancak paylaşılan kitaplıkları, adını söyler, birden çok program arasında paylaşılıyor, bu şekilde paylaşılan bir kütüphane ile messing iyi bir fikir değildir.

Trambolin sarıcı yazma almak. Daha da kötüsü paylaşılan kitaplık karşı bağlanamıyor nesne dosyası seviyesinde, ama dinamik yükleme yapmak zorunda kalıyor. Ama bu çok kendi makale hak ediyor.

Ayarlı ve kodlama mutlu kal.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • How Things Are Made

    How Things A

    17 HAZİRAN 2008
  • Kap Slap

    Kap Slap

    8 Mart 2010
  • The Verge

    The Verge

    8 AĞUSTOS 2006