I'm trying to learn how to use C++ and ODB following this tutorial:
http://www.codesynthesis.com/products/odb/doc/manual.xhtml#2
I've created a Person.hxx file where there is the declaration of class Person as persistent, then I've got thre files Person-odb: .cxx, .hxx, .ixx
Now I should compile Person-odb.cxx with
g++ -I/usr/lib/odb/i686-linux-gnu/include Person-odb.cxx
but it end with:
fatal error: odb/pgsql/version.hxx: No such file or directory. compilation terminated.
I see that there is a file version.hxx but there's no odb/pgsql directory...
what's wrong?
this is Person.hxx where I have defined the persistent class Person:
#ifndef PERSON_HXX
#define PERSON_HXX
#include <string>
#include <odb/core.hxx>
using namespace std;
#pragma db object
class Person {
private:
Person() {
}
friend class odb::access;
#pragma db id auto
unsigned long id_;
std::string email_;
std::string first_;
std::string last_;
unsigned short age_;
public:
Person(const std::string& first, const std::string& last,
unsigned short age);
/* getters */
const std::string& first() const;
const std::string& last() const;
unsigned short age() const;
const std::string& email() const;
/* setters */
void setAge(unsigned short);
void setFirst(const std::string&);
void setLast(const std::string&);
void setEmail(const std::string&);
};
#endif
then I must compile Person.hxx with odb compiler:
odb -d mysql --generate-query --generate-schema Person.hxx
and I get 4 files Person.odb.hxx, .cxx, .sql, .ixx
this is driver.cxx where I have the main program which persists objects:
#include <memory>
#include <iostream>
#include <odb/database.hxx>
#include <odb/transaction.hxx>
#include <odb/mysql/database.hxx>
#include "Person.hxx"
#include "Person-odb.hxx"
using namespace std;
using namespace odb;
int main(int argc, char* argv[]) {
try {
auto_ptr<database> db (new odb::mysql::database (argc, argv));
unsigned long marcoID, loryID, lucaID;
/*Create some persistent Person objects */
Person marco ("Marco", "Di Nicola", 26);
Person luca ("Luca", "La Sala", 22);
Person lory ("Lorenzo", "Vinci", 24);
transaction t (db->begin());
marcoID = db->persist(marco);
lucaID = db->persist(luca);
loryID = db->persist(lory);
t.commit();
} catch (const odb::exception& e) {
cerr << e.what() << endl;
return 1;
}
}
and this is the file Person-odb.hxx
// This file was generated by ODB, object-relational mapping (ORM)
// compiler for C++.
//
#ifndef PERSON_ODB_HXX
#define PERSON_ODB_HXX
#include <odb/version.hxx>
#if (ODB_VERSION != 20200UL)
#error ODB runtime version mismatch
#endif
#include <odb/pre.hxx>
#include "Person.hxx"
#include <memory>
#include <cstddef>
#include <odb/core.hxx>
#include <odb/traits.hxx>
#include <odb/callback.hxx>
#include <odb/wrapper-traits.hxx>
#include <odb/pointer-traits.hxx>
#include <odb/container-traits.hxx>
#include <odb/no-op-cache-traits.hxx>
#include <odb/result.hxx>
#include <odb/simple-object-result.hxx>
#include <odb/details/unused.hxx>
#include <odb/details/shared-ptr.hxx>
namespace odb
{
// Person
template <>
struct class_traits< ::Person >
{
static const class_kind kind = class_object;
};
template <>
class access::object_traits< ::Person >
{
...
#include "Person-odb.ixx"
#include <odb/post.hxx>
#endif // PERSON_ODB_HXX
everything seems to work fine when I perform:
c++ -c Person-odb.cxx
c++ -c driver.cxx
but in the end when I have to link all together with:
c++ -o driver driver.o Person-odb.o -lodb-mysql -lodb
I get:
"undefined reference to `Person::Person(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&, unsigned short)'"
What seems to be your problem is that you didn't install ODB. The Installing ODB page should get you up and running.
You see a version.hxx file, but that's an input file for the ODB compilation process, not for including in your programs.
If you did install it, find out where on your system and add that folder to your compiler include path. Your compilation command then becomes
g++ -I/usr/lib/odb/i686-linux-gnu/include -I/path/to/odb/install/include Person-odb.cxx
Following your edits, I think the issue is that you're not linking to the Person object file, only the Person-odb one.
Compile Person.cxx with
g++ -c Person.cxx
and change your linking command to
g++ -o driver driver.o Person.o Person-odb.o -lodb-mysql -lodb
and the error should be fixed.
Please note that I don't know ODB. I'm trying to figure this out from a pure C++ perspective.
Related
Through the act of separating a set of input and output related functions from other parts of a program, I have encountered a problem with compiling files when functions in a header are placed within a namespace. The following files compile:
main.cpp
#include "IO.h"
int main()
{
testFunction("yikes");
}
IO.h
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
#include <string>
void testFunction(const std::string &text);
#endif
However, when testFunction is placed in a namespace:
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
#include <string>
// IO.h
namespace IO
{
void testFunction(const std::string &text);
}
#endif
within IO.h, and then invoked as IO::testFunction, compilation fails, throwing
undefined reference to `IO::testFunction(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2.exe: error: ld returned 1 exit status`
In each case, IO.cpp is
#include <string>
#include <iostream>
void testFunction(const std::string &text)
{
std::cout << text << std::endl;
}
and the compilation command is g++ -std=c++11 main.cpp IO.cpp, with the compiler being x86_64-w64-mingw32 from TDM-GCC, on Windows 10 Home.
If you change the declaration of your function to be in a namespace you need to implement the function within this namespace aswell.
The signature of your function will be IO::testFunction(...) but you only implemented testFunction(...) so there is no implementation for IO::testFunction(...)
The header file (IO.h):
namespace IO {
void testFunction(const std::string &text);
}
The cpp file (IO.cpp):
#include "IO.h"
// either do this
namespace IO {
void testFunction(const std::string &text) { ... }
// more functions in namespace
}
// or this
void IO::testFunction(const std::string &text) { ... }
This is my main.cpp
#include <iostream>
#include <string>
#include "Tokenizer.h"
using namespace std;
int input;
int main(int argc, char const *argv[]){
Tokenizer obj("yeet");
cout << obj.getString();
cin >> input;
return 0;
}
This is my Tokenizer.h
#ifndef TOKENIZER_H
#define TOKENIZER_H
#include <string>
class Tokenizer{
public:
Tokenizer(std::string m);
std::string getString();
protected:
private:
std::string token;
};
#endif // TOKENIZER_H
This is my Tokenizer.cpp
#include "Tokenizer.h"
#include <string>
Tokenizer::Tokenizer(std::string m){
token=m;
//code
}
std::string Tokenizer::getString(){
return token;
}
when i compile with g++ it works fine and when i open a.exe i get this error.
The procedure entry point
_ZNSt7_cxx1112basic_stringlcSt11char_traitslcESalcEEC1EPKcRKS^_ could not be located in the dynamic link libary c:\"My project path"
(All files are in same folder.)
and i compiled with int without strings it worked fine i guess it is a error with #include <string>
In Mingw You have to explicitly specify libgcc libstdc++ the libraries. Use the following command
g++ Tokenizer.cpp main.cpp -o main -static-libgcc -static-libstdc++
I am sure this is a trivial error. Nontheless I cannot find an error or a solution on Stackoverflow.
I have received above mentioned error for struct Transition, seemingly declared here :
Transition.h:
#ifndef ZOCK_TRANSITION_H
#define ZOCK_TRANSITION_H
#include <iostream>
#include "vec.h"
#include "dir.h"
#include "Board.h"
using std::ostream;
using std::endl;
struct Transition
{
vec fromv;
dir fromd;
vec tov;
dir tod;
Transition();
Transition(vec fromv, dir fromd, vec tov, dir tod);
friend ostream& operator<< (ostream& os, cost Transition& t);
};
Transition swap(Transition& t) const;
#endif// ZOCK_TRANSITION_H
Error Message is :
g++ -std=c++14 -I./inc -c src/Transition.cpp -o build/debug/Transition.o -g3
In file included from ./inc/Board.h:21:0,
from ./inc/Transition.h:19,
from src/Transition.cpp:12:
./inc/Map.h:29:9: error: ‘Transition’ was not declared in this scope
vector<Transition> transitions;
So lets look into Map.h:
#ifndef ZOCK_MAP_H
#define ZOCK_MAP_H
#include <string>
#include <vector>
#include "Transition.h"
using std::string;
using std::vector;
class Map
{
friend class Board;
private:
int height, width;
char ** fields;
vector<Transition> transitions;
public:
enum readfrom
{
str = 0,
file ,
NUM_READFROM //Leave last !
};
Map(string i, readfrom p);
};
#endif// ZOCK_MAP_H
It is unlikely that it is a compiler or linker error, since it seems every file was found correctly. Everything seems to be included correctly, so I am at a dead end.
What dows cause the error or what are common mistakes causing the error ?
I've installed the mimetic library according to the INSTALL instructions.
the following main file compiles without a problem with a gcc-c++ 4.1.2,
but when I upgrade to gcc-c++ 4.4.7 I get an error.
mimetic.cpp:
#include <iostream>
#include <mimetic.h>
using namespace std;
using namespace mimetic;
int main()
{
MimeEntity me;
return 0;
}
error
In file included from /usr/local/include/mimetic/rfc822/header.h:18,
from /usr/local/include/mimetic/header.h:11,
from /usr/local/include/mimetic/mimetic.h:18,
from mimetic.cpp:2:
/usr/local/include/mimetic/rfc822/messageid.h:29: error: expected ‘)’ before ‘thread_id’
the header file:
rfc822/messageid.h
#ifndef _MIMETIC_MESSAGEID_H_
#define _MIMETIC_MESSAGEID_H_
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <string>
#include <mimetic/libconfig.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <mimetic/utils.h>
#include <mimetic/os/utils.h>
#include <mimetic/rfc822/fieldvalue.h>
namespace mimetic
{
/// Message-ID field value
/// On Win32 Winsock library must be initialized before using this class.
struct MessageId: public FieldValue
{
MessageId(uint32_t thread_id = 0 ); // <------ line 29
MessageId(const std::string&);
std::string str() const;
void set(const std::string&);
protected:
FieldValue* clone() const;
private:
static unsigned int ms_sequence_number;
std::string m_msgid;
};
}
#endif
is there some compatibility switch for the gcc ?
So, the problem turns out to be poor configuration of the system, which leaves HAVE_STDINT_H not configured, and thus the uint32_t doesn't get defined, and the error occurs.
I am having a Compile issue.
I have one Class
I have one header file
And of course Main to test my work.
But I am getting compile error, it is out of my understanding what I am doing wrong.
Header File:
#ifndef AGENT_H
#define AGENT_H
using namespace std;
class Agent
{
public:
Agent(string);
virtual ~Agent();
private:
string name;
};
#endif /* AGENT_H */
Agent Class (Agent.cpp)
#include "Agent.h"
using namespace std;
Agent::Agent(string _name)
{
this->name = _name;
}
Agent::~Agent()
{
delete this->name;
}
And my Main:
#include <cstdlib>
#include <iostream>
#include "Agent.h"
using namespace std;
int main(int argc, char** argv)
{
Agent agent1("Danila");
return 0;
}
So I am getting such strange error:
undefined reference to `Agent::Agent(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
/main.cpp:17: undefined reference to `Agent::~Agent()'
/main.cpp:17: undefined reference to `Agent::~Agent()'
Could you guys help me understand whats wrong there?
You need an #include <string> in your header file.
Also, for good practice, keep the using namespaces in your .cpp files, if any.
You compiled without telling the compiler about Agent.cpp. I.e. you need something like this, for g++:
$ g++ main.cpp Agent.cpp -o myprogram