Προς το περιεχόμενο

Χρήση βιβλιοθηκών για τη δημιουργία προγράμματος σε C++


feugatos

Προτεινόμενες αναρτήσεις

Δημοσ.

Γειά σας.

Είμαι νέος στη 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++.

Δημοσ.

Έτσι όπως το έχεις γράψει, το main.cpp αγνοεί το definition της Soldier (Soldier.cpp), γι' αυτό και διαμαρτύρεται ο compiler.

 

Πέραν αυτού, έχεις παραλείψει τον constructor του Soldier. Ο compiler θα χρησιμοποιήσει default constructor, που στην περίπτωσή σου δεν πρέπει.

Δημοσ.
Έτσι όπως το έχεις γράψει, το main.cpp αγνοεί το definition της Soldier (Soldier.cpp), γι' αυτό και διαμαρτύρεται ο compiler.

 

Πέραν αυτού, έχεις παραλείψει τον constructor του Soldier. Ο compiler θα χρησιμοποιήσει default constructor, που στην περίπτωσή σου δεν πρέπει.

 

Το να ορίσω constructor δεν το θεωρώ απαραίτητο σε αυτήν την περίπτωση.

Δεν μου χρειάζεται να κάνω αρχικοποιήσεις κατά τη δημιουργία ενός στιγμιοτύπου

οπότε θα ήταν περιττό να έχω έναν. Τώρα γιατί λες ότι στην περιπτωσή μου δεν πρέπει

δεν το καταλαβαίνω.

 

Όσο για το πρώτο που είπες. Το ζητούμενο αυτό είναι. Να έχω ως shared βιβλιοθήκη το

soldier και να χρησιμοποιήσω από εκεί τον ορισμό της κλάσης ώστε να μην χρειαστεί να

τη γράψω και στο main.cpp.

Δημοσ.

Φυσικά και ο σκοπός της βιβλιοθήκης είναι αυτός που αναφέρεις, πλην όμως εσύ έχεις 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.

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...