feugatos Δημοσ. 14 Νοεμβρίου 2008 Δημοσ. 14 Νοεμβρίου 2008 Γειά σας. Είμαι νέος στη C++. Αυτό που θέλω να κάνω είναι το εξής: Έχω ένα κομμάτι κώδικα το από το οποίο δημιουργώ μια βιβλιοθήκη .so. Θέλω να μάθω πως μπορώ να καλέσω πράγματα που έχει αυτή η βιβλιοθήκη σε ένα πρόγραμμά μου και να τη χρησιμοποιήσω. Πιο συγκεκριμένα έχω τη βιβλιοθήκη libSoldier.so με sourcecode: > #include <iostream> #include <cstring> using namespace std; class Soldier { int ASM; char onoma[15], eponymo[15]; int hmeresAdeias; int wresYpiresias; public: void setASM(int ASM) {this->ASM = ASM;} void setOnoma(char *onoma) {strcpy(this->onoma, onoma);} void setEponymo(char *eponymo) {strcpy(this->eponymo, eponymo);} void setHmeresAdeias(int hmeresAdeias) {this->hmeresAdeias = hmeresAdeias;} void setWresYpiresias(int wresYpiresias) {this->wresYpiresias = wresYpiresias;} int getASM() {return ASM;} char *getOnoma() {return onoma;} char *getEponymo() {return eponymo;} int getHmeresAdeias() {return hmeresAdeias;} int getWresYpiresias() {return wresYpiresias;} void printInfo(); }; void Soldier::printInfo() { cout << this->getASM() << "\n"; cout << this->getEponymo() << ", " << this->getOnoma() << "\n"; cout << "Hmeres Adeias: " << this->getHmeresAdeias() << "\n"; cout << "Wres Ypiresias: " << this->getWresYpiresias() << "\n"; } το αρχείο header soldier.h με sourcecode: > class Soldier; και το αρχείο main.cpp με sourcecode: > #include "libs/soldier.h" main(int nArgs, char *Args[]) { Soldier A; A.setASM(4181); A.setOnoma("Dimitrios"); A.setEponymo("Zarras"); A.setHmeresAdeias(10); A.setWresYpiresias(25); A.printInfo(); } . Για τη δημιουργία της βιβλιοθήκης "έτρεξα" τις εντολές: > gcc -fPIC -c -o soldier.o soldier.cpp gcc -shared -o libSoldier.so soldier.o Ενώ για το main.cpp κάπου διάβασα και έλεγε να καλέσω το gcc ώς εξής: > gcc -o main -L /libs/libSoldier.so main.cpp Το δοκίμασα και δεν έκανε compile. Μου έβγαζε το εξής σφάλμα: > main.cpp: In function ‘int main(int, char**)’: main.cpp:5: error: aggregate ‘Soldier A’ has incomplete type and cannot be defined Απ'οτι καταλαβαίνω για κάποιο λόγο δεν κάνει σωστά το linking ο gcc με αποτέλεσμα να μην διαβάζει το main.cpp καθόλου τον ορισμό της class Soldier από το libSoldier.so. Τι ακριβώς κάνω λάθος/δεν κάνω καθόλου; Τα αρχεία είναι τοποθετιμένα ως εξής: > SoldierManagment/main.cpp SoldierManagment/libs/soldier.h SoldierManagment/libs/libSoldier.so SoldierManagment/libs/soldier.cpp SoldierManagment/libs/soldier.o Ευχαριστώ πολυ. > Χρησιμοποιώ Linux με gcc/g++.
fromaz Δημοσ. 14 Νοεμβρίου 2008 Δημοσ. 14 Νοεμβρίου 2008 Έτσι όπως το έχεις γράψει, το main.cpp αγνοεί το definition της Soldier (Soldier.cpp), γι' αυτό και διαμαρτύρεται ο compiler. Πέραν αυτού, έχεις παραλείψει τον constructor του Soldier. Ο compiler θα χρησιμοποιήσει default constructor, που στην περίπτωσή σου δεν πρέπει.
feugatos Δημοσ. 15 Νοεμβρίου 2008 Μέλος Δημοσ. 15 Νοεμβρίου 2008 Έτσι όπως το έχεις γράψει, το main.cpp αγνοεί το definition της Soldier (Soldier.cpp), γι' αυτό και διαμαρτύρεται ο compiler. Πέραν αυτού, έχεις παραλείψει τον constructor του Soldier. Ο compiler θα χρησιμοποιήσει default constructor, που στην περίπτωσή σου δεν πρέπει. Το να ορίσω constructor δεν το θεωρώ απαραίτητο σε αυτήν την περίπτωση. Δεν μου χρειάζεται να κάνω αρχικοποιήσεις κατά τη δημιουργία ενός στιγμιοτύπου οπότε θα ήταν περιττό να έχω έναν. Τώρα γιατί λες ότι στην περιπτωσή μου δεν πρέπει δεν το καταλαβαίνω. Όσο για το πρώτο που είπες. Το ζητούμενο αυτό είναι. Να έχω ως shared βιβλιοθήκη το soldier και να χρησιμοποιήσω από εκεί τον ορισμό της κλάσης ώστε να μην χρειαστεί να τη γράψω και στο main.cpp.
fromaz Δημοσ. 15 Νοεμβρίου 2008 Δημοσ. 15 Νοεμβρίου 2008 Φυσικά και ο σκοπός της βιβλιοθήκης είναι αυτός που αναφέρεις, πλην όμως εσύ έχεις declaration και definition (inline) στο ίδιο αρχείο. Γεγονός, που εξ' ορισμού αποκλείει τη χρήση της βιβλιοθήκης. Θα το διαπιστώσεις αργότερα, όταν ο linker θα αρχίσει να παραπονιέται για duplicate symbols. Ειδικά η printInfo δεν περνάει με τίποτα. Τα inline μπορούν και δεν μπορούν ανάλογα την περίπτωση. Όμως, μνήμη δεν γλυτώνεις ούτε μοιράζεις. Στο soldier.h κάνεις κάτι που λέγεται "forward declaration", δηλαδή δηλώνεις το class χωρίς το body. Στη γραμμή "Soldier A;" (main) ο compiler δεν γνωρίζει πόση μνήμη θα πρέπει να δεσμεύσει στο stack. Δεν ξέρει τίποτα για το class, πέραν του ονόματος. Το error που παίρνεις οφείλεται σε αυτό. Όσο για τον constructor, το τι θεωρείς απαραίτητο λίγο έχει να κάνει με το πιο είναι το σωστό. Αν ο χρήστης της βιβλιοθήκης σου καλέσει την printInfo(); χωρίς να έχει προηγηθεί κλήση όλων των mutators, τότε θα έχεις ένα ωραίο καραμπουμ (unspecified behaviour). Επί τη ευκαιρία, καλό είναι να έχεις explicit accesibility operators και να μη βασίζεσαι σε defaults. Πρέπει, δηλαδή, να προηγηθεί το "private:" πριν τα data members.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.