Inteligentne linkowanie

Inteligentne linkowanie
RI
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
0

Witam,

chciałbym się dowiedzieć, czy da się zrobić tak (lub raczej: jak to zrobili autorzy bibliotek std), ażeby plik, który zawiera zarówno deklaracje jak i definicje- mógł być załączany do wielu plików w jednym projekcie nie wywołując błędu linkera (że taka a taka funkcja/zmienna została już zdefiniowana).

Można spytać:
po co? przecież od tego jest plik nagłówkowy *.h i *.cpp.

Tak, ale sprawa się komplikuje w przypadku użyciu szablonów.
Rozdzielenie klasy na plik nagłówkowy i definicje w innym pliku (cpp) powoduje zazwyczaj błąd (unresolved external symbol).

Poza tym w przypadku małych klas, które używamy w wielu projektach.. bez sensu jest kompilować statycznego lib'a i załączać 1kb do projektu za każdym razem :|

Zauważcie: jak używacie bilbiotek std::vector czy std::string i innych.. Każdy z tych plików zawiera zarówno deklaracje jak i definicje (wystarczy otworzyć te pliki). Załączamy je w dowolnych plikach, a mimo to nie powoduje to błędu.

I moje pytanie brzmi:
Czy ktoś wie jak to osiągnąć?

n0name_l
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 5 lat
  • Postów:2412
0

Az sam sprawdzilem czy rzeczywiscie te pliki az takie wyjatkowe sa jak piszesz, ale niestety nie ;(

Kopiuj
#ifndef blablabla
#define blablabla
<tutaj zawartosc>
#endif // blablabla
edytowany 1x, ostatnio: Rev
Zobacz pozostały 1 komentarz
RE
co, kto ma je zrobić jak nie ty? masz odpowiednie znaczniki od zamieszczania kodu źródłowego, użyj ich.
n0name_l
Jak bedzie chcial skorzystac to sobie zrobi, jakby znaczniki poprawily czytelnosc tego co napisalem to bym je umiescilem, jakby umieszczenie ich mialo jakikolwiek inny sens to tez bym to zrobil. + "<tutaj zawartosc>", w jakim to jezyku jest napisane, ze nazywasz to "kodem zrodlowym"? Jak sie chcesz kogos czepiac to najpierw pomysl ;)
RE
Umiejętność mojego myślenia ma się bardzo dobrze, dziękuję. Tak, powinieneś użyć tutaj znacznika kodu źródłowego, a w ostateczności (jako, że kodu nie jest dużo) jego liniowej wersji, czyli backticka. Mam nadzieję, że w przyszłości zastosujesz się do moich rad. Proszę wziąć na uwagę, że piszę te słowa jako moderator, a nie troskliwy użytkownik. Tym razem zrobiłem to za ciebie.
n0name_l
Ranga mnie nie interesuje w wymianie pogladow ;) Nadal nie podales konkretnego powodu dla, ktorego mialbym to w tym wypadku zrobic, ale niech bedzie, milego dnia :>
Patryk27
@n0name_l: z tego samego powodu, dla którego na polskim forum nie piszesz po chińsku czy nie wysyłasz postów w base64, powinieneś korzystać także z funkcji formatowania postów ;) Chodzi o klarowność zapisu i łatwość jego odczytu.
RI
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
0

No właśnie nie.. kiedyś myślałem, że ten "trik" tak samo jak #pragma once rozwiązuje problem jednakże..

te triki zapewniają jedynie, że dany plik nagłówkowy nie zostanie załączony podczas kompilacji DANEGO pliku .cpp więcej niż raz,
jednakże są załączane "po razie" do każdego pliku .cpp w projekcie.

a zatem każdy skompilowany plik cpp zawiera identyczne definicje, stąd- przy linkowaniu error: "already defined in.. "

jednakże właśnie te standardowe biblioteki jakoś się wycwaniły.

W książce z której uczyłem się c++ był podobny problem, i pisał tam (pan Grębosz- Pasja) iż stosuje się tzw. smart linking- linker widząc dwie identyczne definicje, po prostu jedną ignoruje.
Jednakże w visualu 2010 nigdzie się tej opcji nie mogę doszukać :|

n0name_l
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 5 lat
  • Postów:2412
0

Masz racje, ale w kodzie nic nie widac na temat jakichs sprytnych rozwiazan.

Edit: Szablony mozna dolaczac wielokrotnie po prostu, ze wzgledu na czas ich konkretyzacji.

edytowany 1x, ostatnio: n0name_l
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:13 dni
0

Przed funkcjami dołączasz inline, nawet jeżeli kompilator to zignoruje to i tak możesz dołączyć taką funkcję wielokrotnie.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

Tak, ale sprawa się komplikuje w przypadku użyciu szablonów.
Twój problem nie istnieje. Pokaż może kod, który ci nie działa ;-)

Czy ktoś wie jak to osiągnąć?
Nie trzeba niczego osiągać. Samo działa.

edytowany 1x, ostatnio: Azarien
RI
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
0

Ok. widzę o co chodzi :p
plik vectora jest tak rozwleczony, że nie zauważyłem, iż wszystkie funkcje definiowane są w ciele klasy.. Dlatego nie ma problemu z wielokrotnym linkowaniem.

jednakże da się coś zrobić w przypadku statycznych obiektów w klasie (muszą być zdefiniowane poza klasą), tak żeby uniknąć podziału na plik *.cpp tej klasy?

czym to motywuje?
prostotą dołączania takich "klas", nie trzeba ściągać lib'ów dla niej, szczególnie jeśli klasa jest mała, i plik cpp składałby się z kilku linijek :p

Nie słyszał ktoś z Was o opcji "smart linking" lub coś w tym rodzaju? Że linker po prostu igronuje powtarzające się (identyczne) definicje?

Azarien,
mam tak w każdym projekcie, jeśli funkcje szablonowe definiuje w odrębnym pliku .cpp, co używając potem tej klasy dostaje błąd "unresolved external symbol"- nie widzi definicji tych funkcji.

przykład, tylko tak symbolicznie:
plik class.h

Kopiuj
template <class A>
class ALFA {
 A  liczba;
 A  funkcja();
};

plik class.cpp

Kopiuj
#include "class.h"

template <class A>
A
ALFA<A:: funkcja() {
 return liczba;
}

plik main.cpp

Kopiuj
#include "class.h"
...
ALFA<int>  p;
p.funkcja();

podczas kompilacji błąd- niezdefiniowana funkcja

edytowany 4x, ostatnio: Rev
RE
Przed wysłaniem postu zawsze upewnij się, że jest on czytelny - przede wszystkim używaj znaczników kodu. W taki sposób, w jaki zrobiłem to teraz za ciebie.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

Azarien,
mam tak w każdym projekcie, jeśli funkcje szablonowe definiuje w odrębnym pliku .cpp, co używając potem tej klasy dostaje błąd "unresolved external symbol"- nie widzi definicji tych funkcji.

Nie rozumiem cię, albo ty mnie nie rozumiesz.
Miałem na mysli, że definicja funkcji szablonowej w pliku .h nie powoduje błędu linkera o wielokrotnej definicji.

edytowany 2x, ostatnio: Azarien
RI
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
0

hm.. nie rozumiemy się nawzajem :p
w pierwszy poście jako "komplikacja" napisałem, że właśnie chodzi mi o rozdzielenie klasy na dwa pliki- .h i .cpp, co powoduje błąd "unresolved external symbol",
dlatego tak zależy mi, ażeby znaleźć sposób na "upakowanie" klasy szablonowej w jednym pliku i ominięcia błędu linkera, a raczej powiedzenie mu:
że powtarzające się definicje ma po prostu pominąć.. a nie częstować mnie FATAL ERROR'em :D

Jerzy Grębosz w swojej książce Pasja (tom 1) opisał dokładnie ten sam problem w rozdziale "Jak rozmieszczać w plikach szablony klas." jeśli ktoś ma, tam jest dokładnie pokazane o co chodzi.. I jako rozwiązanie jest podane ustawienie opcji "smart" w linkerze.
Jednakże nigdzie tego nie mogę znaleźć w VC10 :(

PS przepraszam za nie umieszczenie tak ładnego kodu :p nie wiedziałem o tym : (

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

w pierwszy poście jako "komplikacja" napisałem, że właśnie chodzi mi o rozdzielenie klasy na dwa pliki- .h i .cpp, co powoduje błąd "unresolved external symbol"
W przypadku szablonów tak się właśnie dzieje, a przyczyna jest dość skomplikowana.

dlatego tak zależy mi, ażeby znaleźć sposób na "upakowanie" klasy szablonowej w jednym pliku
No i tak najlepiej zrobić...

i ominięcia błędu linkera, a raczej powiedzenie mu:
że powtarzające się definicje ma po prostu pominąć..
Jakiego błędu, nie ma żadnego błędu. To chciałem powiedzieć, że w przypadku szablonów tak można zrobić, bez żadnego kombinowania.

a nie częstować mnie FATAL ERROR'em
Pokaż kod. Twój problem polega najprawdopodobniej na czymś innym, a czepiłeś się biednego linkera.

edytowany 2x, ostatnio: Azarien
Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:prawie 2 lata
0

@Azarien: to, że nie ma błędu to rzeczywiście kwestia linkera. Nie wiem co mówi o tym standard, ale pewnie tyle, ze "jakoś trzeba zrobić, żeby to działało". A może nie mówi nic. Linker ld rozwiązuje to tak, że symbole związane z szablonami są oznaczone jako weak symbols co powoduje, że napotkanie wielu takich samych symboli podczas linkowania nie powoduje błędu. Gdyby te symbole oznaczone były by jako normalne symbole wtedy błąd o wielokrotnej definicji z pewnością by się pojawił.

Oczywiście w ld nie trzeba niczego konfigurować, żeby to działało, podejrzewam że nigdzie indziej też nie. Autor zapewne popsuł coś innego...


"(...) otherwise, the behavior is undefined".
RI
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
0

Macie rację, musiałem popsuć coś innego ;|
napisany przykład na szybko.. działa.

No nic, ważne, że dowiedziałem się, iż typowana przyczyna błędu jest nieprawdziwa i kwestia leży po mojej stronie, i.. w takim razie- jest do rozwiązania :)
W wolnej chwili znów "popsuję" kod i będę wiercił (bo obecnie zastosowałem kompromis.. program upakowany w jeden plik cpp, zatem nie ma żadnych redefinicji ;x ).

Dzięki za odpowiedzi : )

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

to, że nie ma błędu to rzeczywiście kwestia linkera. Nie wiem co mówi o tym standard, ale pewnie tyle, ze "jakoś trzeba zrobić, żeby to działało"
Standard mówi, że program ma działać. Samo istnienie linkera, jako osobnego od kompilatora programu, to szczegół implementacji danego kompilatora.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.