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;
}
Related
I have the below code which builds successfully when using the new , but undefined reference error when using std::make_unique.
Bar.h
#include <memory>
class Foo
{
public:
Foo(int c) : x(c) {}
private:
int x;
};
class Bar
{
public:
void setpointer()
{
fooPtr.reset( new Foo(x) ); // **** No linker error
// fooPtr = std::make_unique<Foo>(x); // **** Error : Undefined reference to Bar::x
}
static const unsigned int x = 3;
private:
std::unique_ptr<Foo> fooPtr{nullptr};
};
main.cpp
#include "Bar.h"
int main()
{
Bar bar;
bar.setpointer();
return 0;
}
I understand that definition of the static variable is missing and it can be solved by defining as static inline. But, the question is why there is no undefined reference when using new.
I am not able to access member function using pointer.Find the below code and Error message
The Error message is mentioned here
error: request for member ‘getstream’ in ‘* objA.A::getfunction()’, which is of non-class type ‘int’
ret = objA.getfunction()->getstream();
#include <iostream>
using namespace std;
class A {
public:
int *getfunction();
int getstream();
};
int* A::getfunction()
{
static int a;
a= getstream();
return &a;
}
int getstream()
{
return 1;
}
int main()
{
int *ret;
A objA;
ret = objA.getfunction()->getstream();
cout << ret;
return 0;
}
If you want to achieve a syntax like objA.getfunction()->getstream(); in your main function,
you can do it with class A implementation similar to this :
#include <iostream>
using namespace std;
// class A declaration
class A {
public:
// Nested class A::AFunction declaration
class AFunction {
public:
int getstream();
};
private:
AFunction *p_AFunction;
public:
A();
~A();
A::AFunction *getfunction();
}; // class A
// class A member function implementations
A::A() : p_AFunction(new AFunction()) {
}
A::~A() {
delete p_AFunction;
p_AFunction = nullptr;
}
A::AFunction *A::getfunction() {
return p_AFunction;
}
// Nested class A::AFunction member function implementations
int A::AFunction::getstream() {
return 1;
}
// main function
int main() {
A objA;
int ret = objA.getfunction()->getstream();
cout << ret;
return 0;
}
If you want A::getfunction() function to return a function pointer to a member function in class A, and then invoke it in main function, you can have a implementation similar to this :
#include <iostream>
using namespace std;
// class A declaration
class A {
public:
typedef int (A::*AMemberFuncPtr) ();
private:
AMemberFuncPtr fn_getstream;
public:
A();
A::AMemberFuncPtr getfunction();
private:
int getstream();
}; // class A
// class A member function implementations
A::A() : fn_getstream(&A::getstream) {
}
A::AMemberFuncPtr A::getfunction() {
return fn_getstream;
}
int A::getstream() {
return 1;
}
// main function
int main() {
A objA;
int ret = (objA.*objA.getfunction())();
cout << ret;
return 0;
}
Also see the answer to Function pointer to member function.
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?
I am designing a class in C++/CLR that uses a callback function provided by user code.
This works very nicely if the callback function is free ( i.e. not the member of a class ). It is almost the same as in pure C++.
Here is some sample code that works well:
ref class ClassThatUsesCallback
{
public:
typedef void (*callback_t)( String^ );
void setCallback( callback_t pfun )
{
myCallback = pfun;
}
void Run()
{
if( myCallback != nullptr ) {
myCallback("This is a test");
}
}
private:
callback_t myCallback;
};
void FreeFunction( String^ s )
{
Console::WriteLine( "Free Function Callback " + s );
}
int main(array<System::String ^> ^args)
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback( FreeFunction );
theClassThatUsesCallback->Run();
}
However, I would like the callbacked function to be a member of a class in the user code ( so it can make use of and change the attributes of the user code class )
The following code does not compile
ref class ClassThatProvidesCallback
{
public:
void MemberFunction( String^ s )
{
Console::WriteLine( "Member Function Callback " + s );
}
void Run()
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback(
&ClassThatProvidesCallback::MemberFunction );
theClassThatUsesCallback->Run();
}
};
I get this error
error C3374: can't take address of 'ClassThatProvidesCallback::MemberFunction'
unless creating delegate instance
When I research this, I find numerous explanations of how to call un-managed code from managed code ( and vice-versa ) I do not need to do this - all the code involved is managed. So I am hoping that someone can point me to a simple way to this.
This is full solution:
ref class ClassThatUsesCallback
{
public:
void setCallback( Action<String^>^ callback )
{
myCallback = callback;
}
void Run()
{
if( myCallback != nullptr ) {
myCallback("This is a test");
}
}
private:
Action<String^>^ myCallback;
};
ref class ClassThatProvidesCallback
{
public:
void MemberFunction( String^ s )
{
Console::WriteLine( "Member Function Callback " + s );
}
void Run()
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback(gcnew Action<String^>(this,
&ClassThatProvidesCallback::MemberFunction));
theClassThatUsesCallback->Run();
}
};
int main(array<System::String ^> ^args)
{
ClassThatProvidesCallback^ c = gcnew ClassThatProvidesCallback();
c->Run();
return 0;
}
Native C++ style typedef is replaced with .NET Action delegate. Additional parameter this is added to setCallback call, it is required to define the class instance which contains the callback function.
I need to fire an event written in C++ / CLI from an unmanned function in c++.
What is the best way to do this?
Thanks in advance.
I figured out with some help from some help posts on codeproject
Thought of posting it here could be useful for others
#include "stdafx.h"
#include "windows.h"
using namespace System;
using namespace System::Runtime::InteropServices;
class Camera
{
public:
Camera()
{
}
~Camera(){}
void (*test)(void);
void OnNewCameraData();
void StartDataAcquisition();
};
void Camera::StartDataAcquisition()
{
int i;
while(i<10)
{
test();
i++;
Sleep(1000);
}
}
delegate void FunctionToCallDelegate();
ref class CameraAdapter
{
private:
Camera *_camera;
FunctionToCallDelegate ^_Function;
public:
CameraAdapter(FunctionToCallDelegate ^handler)
{
_Function = handler;
}
void Init()
{
_camera = new Camera();
pin_ptr<FunctionToCallDelegate^> tmp = &_Function;
_camera->test = (void (__cdecl *)(void))(Marshal::GetFunctionPointerForDelegate(_Function).ToPointer());
_camera->StartDataAcquisition();
}
~CameraAdapter()
{
delete _camera;
_camera = 0;
}
void OnNewCameraData()
{
Console::WriteLine("Received Frame \n");
}
};
int main(array<System::String ^> ^args)
{
FunctionToCallDelegate ^dsi;
dsi += gcnew FunctionToCallDelegate(gcnew CameraAdapter(dsi), &CameraAdapter::OnNewCameraData);
CameraAdapter ^camera = gcnew CameraAdapter(dsi);
camera->Init();
Console::ReadKey();
return 0;
}