I have written a simple program that use some classes and procol buffers. These classes are to make connecting and sending messages between computers easier. Compilation succeeded. However, linker says:
server.o: In function `main’:
server.cpp:(.text+0x24): undefined
reference to
`dataExchange::Server::Server(unsigned
int)’server.cpp:(.text+0x39):
undefined reference to
`dataExchange::Server::accept()’server.cpp:(.text+0x51): undefined
reference to
`dataExchange::Connection::receive()’
collect2: ld returned 1 exit status
The code:
server.cpp:
#include <iostream>
#include "connection.h"
#include "protocol.pb.h"
using namespace std;
using namespace msg;
using namespace dataExchange;
int main() {
Server server(1234);
while(1) {
Connection con = server.accept();
Annoucement ann = con.receive();
cout << ann.typ() << endl;
}
}
connection.h:
namespace dataExchange {
class SocketMaintenance {
protected:
sockaddr_in addr;
int s;
public:
SocketMaintenance(const unsigned int) throw();
SocketMaintenance(const sockaddr_in, const int) throw();
SocketMaintenance(const SocketMaintenance&) throw();
~SocketMaintenance();
void write(const char*, const int);
};
class Connection {
FileOutputStream* raw_output;
FileInputStream* raw_input;
char buffer[1024];
public:
Connection(const char*, const unsigned int);// throw(WrongAddress);
Connection(const SocketMaintenance&);//throw(ConnectFailed);
void send(const Message&) throw();
Annoucement receive() throw();
};
class Server {
public:
Server(const unsigned int);// throw(BindFailed,ListenFailed);
Connection accept() throw();
};
}
What is the reason the linker fails?
procedure of building:
g++ server.cpp -c; g++ protocol.pb.cc -c; g++ connection.cpp -c;
g++ server.o protocol.pb.o connection.o -lprotobuf
conection.cpp
using namespace std;
using namespace msg;
using namespace google::protobuf;
using namespace google::protobuf::io;
namespace dataExchange {
class SocketMaintenance {
protected:
sockaddr_in addr;
int s;
public:
SocketMaintenance(const unsigned int port) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
s = socket(AF_INET, SOCK_STREAM, 0);
}
SocketMaintenance(const sockaddr_in Addr, const int Socket) {
addr = Addr;
s = Socket;
}
SocketMaintenance(const SocketMaintenance& source) {
addr = source.addr;
s = source.s;
}
~SocketMaintenance() {
close(s);
}
void write(const char* buffer, const int n) {
::write(s, buffer, n);
}
};
class Connection : public SocketMaintenance {
FileOutputStream* raw_output;
FileInputStream* raw_input;
char buffer[1024];
public:
Connection(const char* IP, const unsigned int port) : SocketMaintenance(port) {
if(inet_pton(AF_INET, IP, &addr.sin_addr)<=0) {
throw WrongAddress();
}
if(connect(s, (sockaddr*)&addr, sizeof(addr))<0) {
throw ConnectFailed();
}
raw_output = new FileOutputStream(s);
raw_input = new FileInputStream(s);
}
Connection(const SocketMaintenance& source) : SocketMaintenance(source) {}
~Connection() {
delete raw_output;
}
void send(const Message& msg) throw(EmptyMessage) {
CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
int n = msg.ByteSize();
if(n<=0) throw EmptyMessage();
coded_output->WriteVarint32(n);
delete coded_output;
raw_output->Flush();
msg.SerializeToArray(buffer, n);
SocketMaintenance::write(buffer, n);
}
Annoucement receive() throw() {
CodedInputStream* coded_input = new CodedInputStream(raw_input);
google::protobuf::uint32 n;
coded_input->ReadVarint32(&n);
char *b;
int m;
coded_input->GetDirectBufferPointer((const void**)&b, &m);
Annoucement ann;
ann.ParseFromArray(b, n);
return ann;
}
};
class Server : public SocketMaintenance {
public:
Server(const unsigned int port) : SocketMaintenance(port) {
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (struct sockaddr *)&addr, sizeof(addr))<0) {
throw BindFailed();
}
if(listen(s, 5)<0) {
throw ListenFailed();
}
}
Connection accept() throw() {
sockaddr_in client;
socklen_t client_len;
int client_socket = ::accept(s, (sockaddr*)&client, &client_len);
return Connection(SocketMaintenance(client, client_socket));
}
};
}
Forgot to compile and/or link the"connection.cpp", most likely. I atleast hope you have such a file, which implements all the functions?I think you have some fundamental misunderstandings how the splitting in .h and .cpp works. In the .cpp, you do not simple redeclare the classes, this time with the functions defined inside of them. You need to do like this:
But this is only part of the problem, it seems you need to get a good C++ book. For example, you need to make any inheritence in the header that declares the class.