I have two omnetpp projects: Lab1 and Lab2
From Lab1 .so library is created. Lab 2 is supposed to use this library. It is clear how to import and use modules declared in .ned-files. Problems begin when I try to use message-type from the library (Bitmessage).
bitmessage.msg from the library:
message Bitmessage {
bool bit;
}
sSource.h in Lab2:
#ifndef SSOURCE_H_
#define SSOURCE_H_
#include <omnetpp.h>
#include "bitmessage_m.h"
class sSource : public cSimpleModule
{
protected:
virtual void initialize();
virtual void handleMessage(cMessage *msg);
private:
double p;
};
Define_Module(sSource);
#endif /* SSOURCE_H_ */
sSource.cc - source-file in Lab2 which is suppose to use bitmessage:
#include <sSource.h>
/*virtual*/ void sSource::initialize()
{
p = par("p").doubleValue();
}
/*virtual*/ void sSource::handleMessage(cMessage *msg)
{
if (msg->getArrivalGate() == gate("in"))
{
delete msg;
Bitmessage* bit_msg = new Bitmessage(); // **(!!!)here is error**
int num_outs = this->gateSize("out");
for (int i = 0; i < num_outs; ++i)
{
send(bit_msg->dup(), "out", i);
}
delete bit_msg;
}
else
{
delete msg;
}
}
The error is following:
undefined reference to `Bitmessage::Bitmessage(char const*, int)'
How to deal with it? Maybe the problem is that compiler can't interpret .msg-file from the library?
Related
I'm trying to declare a friend function of a class with static members. I compiled my program in Visual Studio 2017 and faced this compile-time error:
unresolved external symbol "private: static struct Number * user::Link" (?Link#user##0PAUNumber##A)
Here's my code:
#include<iostream>
using namespace std;
typedef struct Number
{
int number;
struct Number *Link;
}
num_t;
class user
{
private:
static num_t *Link;
static int Length;
public:
static void Create()
{
cout << "You called a function." << endl;
Link->number = 1;
}
friend void Show_menu();
};
void Show_menu()
{
user::Create();
}
int user::Length = 1;
num_t user::*Link = nullptr;
int main()
{
return 0;
}
Generally, Is it possible to define a friend function of a class with static members in C++? If so, how do I fix the problem above?
I think you wanted num_t* user::Link = nullptr;.
The error has nothing to do with the declared friend.
I'm trying to learn c++ so, I try to implement the observer patterns from the book Game Progamming Patterns but I'm always getting Segmentation Fault.
Searching arround I saw that Segmentation fault happens when a program try to access a non allocated memory. So I tried hard to fix it, but I can't. Someone can help me?
Here is my code:
Observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include "EntityAndEvent.h"
#include "Subjects.h"
class Observer
{
private:
Observer* next_;
public:
Observer()
: next_(nullptr)
{}
virtual void onNotify(const Entity& entity, Event::Type event) = 0;
// Other stuff...
friend class Subjects;
};
#endif
Achievements.cpp
#ifndef ACHIEVEMENTS_CPP
#define ACHIEVEMENTS_CPP
#include "Observer.h"
#include <vector>
class Achievements : public Observer
{
public:
enum Type{
FELL_OFF,
AWAKE_ON
};
private:
std::vector<Type> done{};
public:
virtual void onNotify(const Entity&, Event::Type);
void unlock(Achievements::Type);
void printDone();
};
void Achievements::onNotify(const Entity& entity, const Event::Type event)
{
switch (event)
{
case Event::Type::ENTITY_FELL:
if(entity.isHero())
unlock(Achievements::Type::FELL_OFF);
break;
case Event::Type::ENTITY_AWAKE:
if(entity.isHero())
unlock(Achievements::Type::AWAKE_ON);
break;
default:
break;
}
};
void Achievements::unlock(Achievements::Type achiev)
{
done.push_back(achiev);
}
void Achievements::printDone()
{
// assert(done.size());
for(size_t i{0}; i < done.size(); i++)
{
std::cout << done[i] << "\n";
}
};
EntityAndEvent.cpp (i create this just to work with observer and subjects)
#ifndef ENTITY_AND_EVENT_H
#define ENTITY_AND_EVENT_H
class Entity
{
public:
inline const bool isHero() const {return true;}
};
class Event
{
public:
enum Type{
ENTITY_FELL,
ENTITY_AWAKE
};
};
#endif
Subjects.h
#ifndef SUBJECT_H
#define SUBJECT_H
#include "Observer.h"
#include <vector>
class Observer;
class Subjects
{
private:
// when implements this, prefer to use linked list or another optimized algorithms
Observer* head_{};
protected:
void notify(const Entity& Entity, Event::Type event);
public:
Subjects() : head_(NULL)
{};
~Subjects() {}
void addObserver(Observer* observer);
// const int getNumObs() const {return num_obs_;}
};
#endif
Subjects.cpp
#include "Subjects.h"
#include <cassert>
void Subjects::notify(const Entity& entity, Event::Type event)
{
Observer* observer = head_;
while (observer != NULL)
{
observer->onNotify(entity, event);
observer = observer->next_;
};
};
void Subjects::addObserver(Observer* observer)
{
if (head_ != nullptr)
observer->next_ = head_;
head_ = observer;
};
Physics.cpp (i create this just to populates the subject)
#ifndef PHYSICS_H
#define PHYSICS_H
#include "Subjects.h"
#include "EntityAndEvent.h"
class Physics: public Subjects
{
private:
public:
void update(const Entity& entity)
{
if (entity.isHero())
{
notify(entity, Event::Type::ENTITY_AWAKE);
};
};
};
#endif
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "Achievements.cpp"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
#include "Subjects.cpp"
int main()
{
Physics *p{};
Entity e{};
Achievements *achiev{};
p->addObserver(achiev);
p->update(e);
return 0;
}
With Physics *p{}; you are declaring a pointer, but it currently does not point to a valid object (it is being initialized as nullptr here). Therefore, calling p->addObserver results in a segmentation fault. You should be able to confirm this by running the program in a debugger.
Why are you using a pointer here? Change Physics *p{}; to Physics p{};.
Disclaimer: Since your code is definitely not a minimum example I didn't look into the whole code or even tried to compile it. I'm only posting an answer because there is a clear error in the main function (use of an invalid pointer) that results in a segmentation fault.
first, tks for the reply. #darcamo that works. I dont know why it was declared as pointer.
I fixed that, so if anyone else have the same doubt check below:
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
int main()
{
Physics p{};
Entity e{};
Achievements achiev{};
Observer* ptr_achiev{&achiev};
p.addObserver(ptr_achiev);
p.update(e);
return 0;
}
Believe me when I tell you that I searched online, but did not find the answer.
I have 5 files:
main.cpp
Game.cpp
Game.hpp
Window.cpp
Window.hpp
The content is below :
#include "Window.hpp"
#include "Game.hpp"
int main()
{
// Program entry point
Game game;
while (!game.GetWindow()->IsDone()){
// game loop here
game.HandleInput();
game.Update();
game.Render();
}
return 0;
}
This is the Game.cpp
#include "Window.hpp"
class Game {
public:
Game(): m_window("Chapter 2", sf::Vector2u(800,600)) {
m_mushroomTexture.loadFromFile("images.png");
m_mushroom.setTexture(m_mushroomTexture);
}
~Game(){}
void HandleInput() {
}
void Update() {
m_window.Update();
MoveMushroom();
}
void Render() {
m_window.BeginDraw();
m_window.Draw(m_mushroom);
m_window.EndDraw();
}
// Getting a point to the window
Window* GetWindow(){
}
private:
void MoveMushroom(){
sf::Vector2u l_windSize = m_window.GetWindowSize();
sf::Vector2u l_textSize = m_mushroomTexture.getSize();
if ((m_mushroom.getPosition().x > l_windSize.x - l_textSize.x and m_increment.x > 0) or \
(m_mushroom.getPosition().x < 0 and m_increment.x < 0)) {
m_increment.x = -m_increment.x;
}
if ((m_mushroom.getPosition().y > l_windSize.y - l_textSize.y and m_increment.y > 0) or \
(m_mushroom.getPosition().y < 0 and m_increment.y < 0)) {
m_increment.y = -m_increment.y;
}
m_mushroom.setPosition( m_mushroom.getPosition().x + m_increment.x, m_mushroom.getPosition().y + m_increment.y);
}
Window m_window;
sf::Texture m_mushroomTexture;
sf::Sprite m_mushroom;
sf::Vector2i m_increment;
};
Game.hpp
#pragma once
#include "Window.hpp"
#include <SFML/Graphics.hpp>
class Game {
public:
Game();
~Game();
void HandleInput();
void Update();
void Render();
// Getting a point to the window
Window* GetWindow();
private:
void MoveMushroom();
Window m_window;
sf::Texture m_mushroomTexture;
sf::Sprite m_mushroom;
sf::Vector2i m_increment;
};
Window.cpp
#include <SFML/Graphics.hpp>
#include <string>
class Window {
public:
// constructor
Window() {Setup("Window", sf::Vector2u(640,480));}
// we have 2 constructors because there 2 ways to instantiate a class
Window(const std::string& l_title, const sf::Vector2u& l_size) {
Setup(l_title, l_size);
}
~Window() { Destroy(); }
void BeginDraw(){
m_window.clear(sf::Color::Black);
}
void EndDraw(){
m_window.display();
}
void Update(){
sf::Event event;
while (m_window.pollEvent(event)) {
if (event.type == event.Closed) {
m_isDone = true;
} else if (event.type == sf::Event::KeyPressed and event.key.code == sf::Keyboard::F5){
ToggleFullscreen();
}
}
}
bool IsDone(){
return m_isDone;
}
bool IsFullscreen(){
return m_isFullscreen;
}
sf::Vector2u GetWindowSize() {
return m_windowSize;
}
void ToggleFullscreen(){
m_isFullscreen = !m_isFullscreen;
Destroy();
Create();
}
void Draw(sf::Drawable& l_drawable){
m_window.draw(l_drawable);
}
private:
void Setup(const std::string& l_title, const sf::Vector2u& l_size) {
m_windowTitle = l_title;
m_windowSize = l_size;
m_isFullscreen = false;
m_isDone = false;
Create();
}
void Destroy(){
m_window.close();
}
void Create() {
// the same as
// if (m_isFullscreen) {
// auto_style = sf::Style::Fullscreen;
// } else {
// auto_style = sf::Style::Default;
// }
auto style = (m_isFullscreen ? sf::Style::Fullscreen : sf::Style::Default);
m_window.create({m_windowSize.x, m_windowSize.y, 32}, m_windowTitle, style);
}
sf::RenderWindow m_window;
sf::Vector2u m_windowSize;
std::string m_windowTitle;
bool m_isDone;
bool m_isFullscreen;
};
Window.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <string>
class Window {
public:
// constructor
Window();
// we have 2 constructors because there 2 ways to instantiate a class
Window(const std::string& l_title, const sf::Vector2u& l_size);
~Window();
void BeginDraw();
void EndDraw();
void Update();
bool IsDone();
bool IsFullscreen();
sf::Vector2u GetWindowSize();
void ToggleFullscreen();
void Draw(sf::Drawable& l_drawable);
private:
void Setup(const std::string& l_title, const sf::Vector2u& l_size);
void Destroy();
void Create();
sf::RenderWindow m_window;
sf::Vector2u m_windowSize;
std::string m_windowTitle;
bool m_isDone;
bool m_isFullscreen;
};
The problem is that when i try to build my project i get a linker error.
/tmp/ccxbe5nA.o: In function `main':
main.cpp:(.text+0x26): undefined reference to `Game::Game()'
main.cpp:(.text+0x35): undefined reference to `Game::GetWindow()'
main.cpp:(.text+0x3d): undefined reference to `Window::IsDone()'
main.cpp:(.text+0x53): undefined reference to `Game::HandleInput()'
main.cpp:(.text+0x62): undefined reference to `Game::Update()'
main.cpp:(.text+0x71): undefined reference to `Game::Render()'
main.cpp:(.text+0x87): undefined reference to `Game::~Game()'
main.cpp:(.text+0xac): undefined reference to `Game::~Game()'
collect2: error: ld returned 1 exit status
I am compiling first with the following command :
g++ -std=c++11 -c main.cpp Window.cpp Game.cpp
No errors during the compilation stage. When I try to link it, I get the error message from above. The command used is this :
g++ main.o Game.o Window.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
By defining the same class differently in different places, your program violates One Definition Rule:
[basic.def.odr]/5 There can be more than one definition of a class type ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
— each definition of D shall consist of the same sequence of tokens; and...
Emphasis mine.
Remove class definition from Game.cpp, only leave member function definitions, like this:
Game::Game(): m_window("Chapter 2", sf::Vector2u(800,600)) {...}
void Game::Update() {...}
// and so on for other members
And similarly for Window.
You define each class twice, which is incorrect.
In your .cpp files it needs to provide definitions for functions declared but not defined in the headers.
E.g., Windows.cpp should include Windows.hpp and contain:
bool Windows::IsDone() {
return m_isDone;
}
I have the following code in io.h:
#include <iostream>
#include "shape.h"
class IODevice { // Interface for displaying CAD objects
public:
virtual void operator << (const Circle& c) = 0;
virtual void operator << (const Line& c) = 0;
};
class CmdIODevice : public IODevice {
void operator << (const Circle& c);
void operator << (const Line& c);
};
and shape.h :
#pragma once
#include "io.h"
class Shape {
public:
virtual void display(IODevice& ioDevice) = 0;
};
class Circle : public Shape {
public:
void display(IODevice& ioDevice);
};
class Line : public Shape {
public:
void display(IODevice& ioDevice);
}
};
and get the following error when I declare the virtual operator in IODevice:
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int
Apparently Circle is not seen by the compiler, I do not understand, please help.
#include "Calc.h"
#include<iostream>
#include <windows.h>
#include <WINERROR.H.>
typedef void (WINAPI * PCTOR) ();
int main()
{
HMODULE hMod = LoadLibrary (L"Calci.dll");
if (NULL == hMod)
{
printf ("LoadLibrary failed\n");
return 1;
}
CCalc *pCCalc = (CCalc *) malloc (sizeof (CCalc));
if (NULL == pCCalc)
{
printf ("memory allocation failed\n");
return 1;
}
PCTOR pCtor = (PCTOR) GetProcAddress (hMod, "CCalc");//127 error
int err = GetLastError();
if (NULL == pCtor)
{
printf ("GetProcAddress failed\n");
return 1;
}
__asm { MOV ECX, pCCalc };
pCtor ();
return 0;
}
//dll file
#include <tchar.h>
#ifdef CALC_EXPORTS
#define CALC_API __declspec (dllexport)
#else
#define CALC_API __declspec (dllimport)
#endif
#define SOME_INSTN_BUF 260
class CALC_API CCalc
{
private:
char m_szLastUsedFunc[SOME_INSTN_BUF];
public:
CCalc ();
int Add (int i, int j);
int Sub (int i, int j);
TCHAR* GetLastUsedFunc ();
};
Use dumpbin.exe to check the exact name of the export in the DLL. Maybe it doesn't exist at all?
If you have a chance to use import library instead of LoadLibrary API, it is better.
You're invoking GetProcAddress (hMod, "CCalc"), however "CCalc" isn't the name of a function: it's the name of a class.
You're trying to load the address of the CCalc::CCalc default constructor: to do that, use a tool (e.g. dumpbin) to discover the "decorated" name of the constructor.
However instead of trying to dynamic-load and invoke the constructor, a more usual way to implement this functionality would be to create a static factory method in the DLL, e.g. like this:
class CALC_API CCalc
{
public:
static CCalc* create() { return new CCalc(); }
private:
//doesn't need to be public because users instantiate this class using
//the static create method
CCalc();
public:
virtual int Add (int i, int j);
virtual int Sub (int i, int j);
virtual TCHAR* GetLastUsedFunc ();
virtual ~CCalc() {}
};
Then use GetProcAddress to get the address of the static CCalc::create function, which because it's static you can invoke without using assembly to mess with ECX.
You can't use GetProcAddress for classes. This does not work. Only functions you can resolve their names are unmangled "C" functions.
For example:
extern "C" __declspec(dllexport) CCalc *create_calc()
{
return new CCalc;
}
Now, you can resolve it using.
GetProcAddress(halnder,"create_calc");
As create_calc is not-mangled function.
Also you will have to provide abstract API class without implementation and make CCalc inherit ACalc, otherwise you'll get unresolved symbols tying to compile your application. Because actual add and remove member functions are not known to the application.
class ACalc {
public:
virtual add(int i,int j) = 0;
...
virtaul ~ACalc() {}
};
class CCalc : public ACalc {
public:
virtual add(int i,int j) { ... };
...
};
And in the main program
ACalc *ptr= call_for_dll_function