I have a Problem and i am completely stuck.
First i show you the code:
Config for Building(NarviConfig.h):
#pragma once;
namespace Narvi
{
#ifdef NARVI_EXPORTS
#define _NarviExport __declspec(dllexport)
#else
#define _NarviExport __declspec(dllimport)
#endif
}
//-------------------------------------------
I have 2 Classes in a DLL like this:
The first One(NarviRoot.h):
Header:
#pragma once
#include "NarviConfig.h"
#include "NarviWindow.h"
namespace Narvi
{
class _NarviExport NarviRoot
{
public:
NarviRoot();
~NarviRoot();
public:
bool Init(void);
private:
NarviWindow* mWindow;
};
}
Source:-----------------------------
#include "NarviRoot.h"
namespace Narvi
{
NarviRoot::NarviRoot()
{
}
NarviRoot::~NarviRoot()
{
delete mWindow;
}
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
}
//-----------------------------------------------------------------
The window(NarviWindow.h):
Header
#pragma once
#include "NarviConfig.h"
namespace Narvi
{
class _NarviExport NarviWindow
{
public:
NarviWindow();
~NarviWindow();
};
}
Source:--------------------------------
#include "NarviWindow.h"
namespace Narvi
{
NarviWindow::NarviWindow()
{
}
NarviWindow::~NarviWindow()
{
}
}
And this is my Testapp
mRoot = new Narvi::NarviRoot();
mRoot->Init();
It seems to work, but the program crashes when calling
mWindow = new NarviWindow();
Inside of
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
and i can't figure out why.
If i write:
NarviWindow* mWindow = new NarviWindow();
it doesn't crash.
The constructor of NarviWindow is doing nothing, but it seems he can't access the private member mWindow.
I am pretty sure it is a simple error i made, but i can't see the wood for the trees.
Thank you! :)
Related
I'm trying to put a bunch of sounds in a std::vector because it's very convenient.
I'm using an auxiliary variable called laser, load the sound into it and, if it's everything ok, push_back into the vector.
When I try to play any the sound, nothing happens, not even error messages which should be printed if anything goes wrong.
Just for curiosity I made laser static and voilá, it works flawlessly (or it seems to).
I'd like to know why.
Header file:
// audio_system.h
#ifndef KUGE_HEADERS_AUDIO_SYSTEM_H_
#define KUGE_HEADERS_AUDIO_SYSTEM_H_
#include "event.h"
#include "system.h"
#include "../sdl2_wrappers/sdl2_wrappers.h"
#include "../include/resources_path.h"
#include <vector>
namespace kuge {
class AudioSystem : virtual public System {
public:
AudioSystem(EventBus& bus): System(bus) {}
void handleEvent(const Event& event);
static bool loadResources();
private:
static void generateRandomSequence();
static std::vector<ktp::SDL2_Sound> lasers_;
};
} // end namespace kuge
#endif // KUGE_HEADERS_AUDIO_SYSTEM_H_
cpp file:
#include "event_bus.h"
#include "audio_system.h"
std::vector<ktp::SDL2_Sound> kuge::AudioSystem::lasers_{};
void kuge::AudioSystem::generateRandomSequence() {}
void kuge::AudioSystem::handleEvent(const Event& event) {
switch (event.getType()) {
case EventTypes::LaserFired:
if (lasers_[0].play() == -1) {
ktp::logSDLError("laser_.play");
}
break;
default:
break;
}
}
bool kuge::AudioSystem::loadResources() {
static ktp::SDL2_Sound laser{}; // here! If I don't make this static, nothing happens
if (!laser.loadSound(ktp::getResourcesPath() + "sounds/laser2.wav")) {
return false;
} else {
lasers_.push_back(laser);
}
ktp::logMessage("AudioSystem: resources loaded.");
return true;
}
OK, so following the advices from the comments, I've made the following changes to make ktp::SDL2_Sound class follow the rule of 0 and now it works without the need to set the laser variable to static. This solves the problem, but I'm still not sure why it worked being static.
class SDL2_Sound {
public:
//~SDL2_Sound() { free(); } // now I don't need any destructor
bool loadSound(const std::string& path);
int play(int loops = 0);
private:
void free();
// Mix_Chunk* sound_ = nullptr; // old raw pointer
std::shared_ptr<Mix_Chunk> sound_{};
};
/* void ktp::SDL2_Sound::free() {
if (sound_ != nullptr) {
Mix_FreeChunk(sound_);
sound_ = nullptr;
}
} */
bool ktp::SDL2_Sound::loadSound(const std::string& path) {
//free();
sound_.reset(Mix_LoadWAV(path.c_str()), &Mix_FreeChunk);
//sound_ = Mix_LoadWAV(path.c_str());
if (sound_ == nullptr) {
ktp::logSDLError("Mix_LoadWAV", path);
return false;
}
return true;
}
App.h:
#ifndef APP_H
#define APP_H
#include <SFML/Graphics.hpp>
#include <vector>
#include "RoomManager.h"
typedef unsigned int uint;
class App {
private:
sf::RenderWindow window;
sf::Event evt;
uint screen_width = 0;
uint screen_height = 0;
sf::Clock deltaClock;
float deltaTime = 0.0f;
RoomManager& roomManager = RoomManager::GetInstance();
std::vector<sf::Sprite> allDrawables;
App() { }
~App() { }
public:
static App& GetInstance() {
static App instance;
return instance;
}
void CreateWindow(uint width, uint height) {
screen_width = width;
screen_height = height;
window.create(sf::VideoMode(screen_width, screen_height), "Point'n'click adventure");
}
void Update() {
while (window.isOpen()) {
deltaTime = deltaClock.restart().asSeconds();
while (window.pollEvent(evt)) {
if (evt.type == sf::Event::EventType::Closed)
window.close();
}
Draw();
}
}
void ResizeScreen(uint width, uint height) {
screen_width = width;
screen_height = height;
window.setSize(sf::Vector2u(screen_width, screen_height));
}
void AddDrawable(sf::Sprite& sprite) {
allDrawables.push_back(sprite);
}
void Draw() {
window.clear();
for (int i = 0; i < allDrawables.size(); i++) {
window.draw(allDrawables[i]);
}
window.display();
}
};
#endif
DrawableEntity.h:
#ifndef DRAWABLEENTITY_H
#define DRAWABLEENTITY_H
#include <SFML/Graphics.hpp>
#include "App.h"
class DrawableEntity {
private:
sf::Texture backgroundTexture;
sf::Sprite backgroundSprite;
public:
DrawableEntity() {
App::GetInstance().AddDrawable(backgroundSprite);
}
~DrawableEntity() { }
void LoadTexture(const std::string texturePath) {
backgroundTexture.loadFromFile(texturePath);
backgroundSprite.setTexture(backgroundTexture);
}
};
#endif
RoomManager.h:
#ifndef ROOMMANAGER_H
#define ROOMMANAGER_H
#include <SFML/Graphics.hpp>
#include <vector>
#include "Room.h"
class RoomManager {
private:
std::vector<Room> rooms;
public:
static RoomManager& GetInstance() {
static RoomManager instance;
return instance;
}
void AddRoom(Room room) {
rooms.push_back(room);
}
};
#endif
Room.h:
#ifndef ROOM_H
#define ROOM_H
#include <SFML/Graphics.hpp>
#include "App.h"
#include "DrawableEntity.h"
class Room {
private:
DrawableEntity background;
public:
Room(const std::string backgroundTexturePath) {
background.LoadTexture(backgroundTexturePath);
}
~Room() { }
};
#endif
main.cpp:
#include <SFML/Graphics.hpp>
#include "App.h"
using namespace sf;
int main() {
App& app = App::GetInstance();
RoomManager& roomManager = RoomManager::GetInstance();
app.CreateWindow(1920, 1080);
roomManager.AddRoom(Room("room_0_background.jpg"));
app.Update();
return 0;
}
My idea here is that whenever I would create DrawableEntity object, it would automatically add its sprite to allDrawables vector in App. The above code throws me C2653 error saying that "'App' is not a class or namespace name". The error appears in DrawableEntity() constructor, at line where I call AddDrawable() method. It's been a while since I coded in C++ (now I code mostly in C#) and I'm not sure how to fix this.
[Note: As, you haven't shared DrawableEntity() constructor code(I didn't find any) I am assuming your problem might be the following. If the following solution does not solve your issue, please share DrawableEntity() constructor code.]
You must have called AddDrawable() as following:
App& appInstance = App::GetInstance();
appInstance::AddDrawable(); // it is wrong
You shouldn't call like above
Rather do the following:
App& appInstance = App::GetInstance();
appInstance.AddDrawable(); // it is correct
Edit(Possible solution, this must be happening in your code):
I guess #drescherjm is right. Please, take a careful look at the code snippets below. I have tested some codes similiar like your code structure:
so_test.cpp file:
#include <cstdio>
#include "so_header.h"
int main() {
A& objA = A::getInstance();
int xa = objA.getX();
printf("xa: %d\n", xa);
B& objB = B::getInstance();
int xb = objB.getX();
printf("xb: %d\n", xb);
return 0;
}
so_header.h file:
#ifndef CLASS_A
#define CLASS_A
#include <cstdio>
#include "so_header_2.h"
class A {
private:
int x = 100;
A(){}
public:
static A& getInstance() {
static A obj;
return obj;
}
int getX() {
return x;
}
void print() {
B& objB = B::getInstance();
int xb = objB.getX();
printf("xb: %d\n", xb);
}
};
#endif
so_header_2.h:
#ifndef CLASS_B
#define CLASS_B
#include <cstdio>
#include "so_header.h"
class B {
private:
int x = 200;
B(){}
public:
static B& getInstance() {
static B obj;
return obj;
}
int getX() {
return x;
}
void print() {
A& objA = A::getInstance();
int xa = objA.getX();
printf("xa: %d\n", xa);
}
};
#endif
When I compile so_test.cpp, I get the follwowing error(using mingw compiler):
In file included from so_header.h:6:0,
from so_test.cpp:2:
so_header_2.h: In member function 'void B::print()':
so_header_2.h:21:3: error: 'A' was not declared in this scope
A& objA = A::getInstance();
^
so_header_2.h:21:6: error: 'objA' was not declared in this scope
A& objA = A::getInstance();
^
so_header_2.h:21:13: error: 'A' is not a class, namespace, or enumeration
A& objA = A::getInstance();
The reason is in print function of A, A is calling B and in print function of B, B is calling A.
Your code structure follows a similiar pattern. Let's start from DrawableEntity.
> DrawableEntity calls App
> App calls RoomManager
> RoomManager calls Room
> Room calls App and DrawableEntity(notice, the order here. App is called before DrawableEntity, and so loop has come back to App)
> App calls RoomManager...and ...so on...
So, the loop is:
DrawableEntity -> App -> RoomManager -> Room -> App -> RoomManager -> ...
As, App is the start of the loop or the first object in the loop to be called, you're getting error recognizing "App" class...cause, you started declaring App, but you've never finished declaring it, and in the middle of declaring it, you are trying to use it. So, you're basically trying to use something that hasn't even seen the light of existence(An analogy could be: its still in womb, not born yet...).
This has happended with your code.
To solve your problem, you need to reorganize your code structure a bit. Just break the cycle(i.e. loop) of call dependency, and you'd be okay.
There are 1 main class and 3 classes: Main, MLME, MAC and Network.
I would want an MLME object to be created within the MAC object upon calling the constructor of the MAC. Then share the same object to the Network object when calling the Network constructor.
This without making the MLME object global or allocating memory with malloc() or new.
I believe this should be done with references which I don't understand fully. Also there might have to be some initializer-list in Network.cpp? I am more experienced with C than C++ and have tried a lot in order to understand all of this.
This is some of my thoughts of the structure, header and cpp files:
Main.cpp
#include "MAC.h"
#include "Network.h"
int main() {
MAC mac();
Network network(mac);
return 0;
}
Here is the MLME part to be shared:
MLME.h
#ifndef MLME_H_INCLUDED
#define MLME_H_INCLUDED
class MLME {
public:
MLME();
};
#endif
MLME.cpp
#include "MLME.h"
MLME::MLME() {}
The MAC class:
MAC.h
#ifndef MAC_H_INCLUDED
#define MAC_H_INCLUDED
#include "MLME.h"
class MAC {
private:
MLME mlme; // NULLED ?
public:
MAC();
MLME getMLME();
};
#endif
MAC.cpp
#include "MAC.h"
MAC::MAC() {
mlme = MLME:MLME();
}
MLME MAC::getMLME() {
return mlme;
}
The Network class:
Network.h
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include "MLME.h"
class Network {
private:
MLME& mlme;
public:
Network(MAC mac);
};
#endif
Network.cpp
#include "Network.h"
class MAC;
Network::Network(MAC mac) {
mlme = mac.getMLME();
}
You're close, but:
The Network::Network constructor should take MAC by reference, like so: Network::Network(MAC& mac). Currently you take a copy, which means taking a copy of MLME as well.
In addition, the Network::Network constructor should use an initializer list to initialize mlme. So the full form would be:
Network::Network(MAC& mac) : mlme(mac.getMLME()) {}
MAC::getMLME() should return a reference to MLME: MLME& MAC::getMLME(). Otherwise you return a copy.
The explicit construction of MLME in the MAC constructor is not needed: it is already default-constructed.
You may want to prevent copying of MLME instances by saying MLME(const MLME&) = delete. If it is really a shared resource, you want any changes to go back to the shared instance. Making it impossible to copy MLME instances will prevent you from accidentally making or modifying a copy.
In your main function: MAC mac() does not do what you think it does. Remove the () or you get a "most vexing parse" error.
Main.cpp
int main() {
MAC mac;
Network network(mac);
mac.set(10);
mac.print();
network.print();
mac.set(11);
mac.print();
network.print();
return 0;
}
MLME.h
#ifndef MLME_H_INCLUDED
#define MLME_H_INCLUDED
#include "iostream"
using namespace std;
class MLME {
private:
int i;
public:
MLME();
void print();
void set(int in);
};
#endif
MLME.cpp
#include "MLME.h"
MLME::MLME() {}
void MLME::print() { cout << 'i' << i << endl; }
void MLME::set(int in) {
i = in;
}
MAC.h
#ifndef MAC_H_INCLUDED
#define MAC_H_INCLUDED
#include "MLME.h"
class MAC {
private:
MLME mlme; // NULLED ?
public:
MAC();
MLME& getMLME();
void print();
void set(int in);
};
#endif
MAC.cpp
#include "MAC.h"
MAC::MAC() {
mlme = MLME();
}
MLME& MAC::getMLME() {
return mlme;
}
void MAC::print() {
mlme.print();
}
void MAC::set(int in) {
mlme.set(in);
}
Network.h
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include "MAC.h"
class Network {
private:
MLME& mlme;
public:
Network(MAC& mac);
void print();
};
#endif
Network.cpp
#include "Network.h"
Network::Network(MAC& mac) : mlme(mac.getMLME()) {}
void Network::print() {
mlme.print();
}
output
i10
i10
i11
i11
I'm facing a problem using forward declaration, and I don't know how to fix it. Here's my files:
BubblePlug.h
#ifndef _BUBBLEPLUG_
#define _BUBBLEPLUG_
#include "IPlug_include_in_plug_hdr.h"
#include "resource.h"
#include "IControl.h"
class IPianoRoll;
class IMidiEngine;
class BubblePlug: public IPlug
{
private:
public:
IMidiEngine *pMidiEngine;
IPianoRoll *pPianoRoll;
BubblePlug(IPlugInstanceInfo instanceInfo);
~BubblePlug();
};
#endif // !_BUBBLEPLUG_
BubblePlug.cpp
#include "BubblePlug.h"
#include "IPlug_include_in_plug_src.h"
#include "IPianoRoll.h"
#include "IMidiEngine.h"
BubblePlug::BubblePlug(IPlugInstanceInfo instanceInfo) : IPLUG_CTOR(10, 1, instanceInfo) {
pPianoRoll = new IPianoRoll(this, 8, 8);
pMidiEngine = new IMidiEngine(this);
}
BubblePlug::~BubblePlug() {
delete pPianoRoll;
delete pMidiEngine;
}
IPianoRoll.h
#ifndef _IPIANOROLL_
#define _IPIANOROLL_
#include "IMidiEngine.h"
class IPianoRoll : public IControl
{
private:
BubblePlug *pBubblePlug;
public:
IPianoRoll(BubblePlug *bubbleplug, int x, int y) : IControl(bubbleplug, IRECT(x, y, x + 10, y + 10)), pBubblePlug(bubbleplug) {
}
~IPianoRoll() {
};
bool Draw(IGraphics *pGraphics) {
return true;
}
void Random(bool onlyScore = false) {
pBubblePlug->pMidiEngine->Init();
}
void Start() {
}
};
#endif // !_IPIANOROLL_
IMidiEngine.h
#ifndef _IMIDIENGINE_
#define _IMIDIENGINE_
class IMidiEngine
{
private:
BubblePlug *pBubblePlug;
public:
IMidiEngine(BubblePlug *bubbleplug) : pBubblePlug(bubbleplug) {
}
~IMidiEngine() {
};
void Init(bool randomScore = true) {
pSamplwhk->pPianoRoll->Start();
}
};
#endif // !_IMIDIENGINE_
when I compile, it says around pSamplwhk->pPianoRoll->Start();:
use of undefined type 'IPianoRoll'
left of '->Start' must point to class/struct/union/generic type
VS2015 find each element writing the code (I've no problem), it happens only when I compile (Build).
Why? I pass BubblePlug and I do forward of both IPianoRoll and IMidiEngine, including them in order (on BubblePlug.cpp).
IMidiEngine should know everythings about IPianoRoll (which it is included first).
At least, I should have problem at "runtime", why at compile?
Can you help me to understand the problem and how to fix it? Thanks.
IPianoRoll.h includes IMidiEngine.h, so no matter in which order you include the two files, the definition of IPianoRoll will always come after the init function where it is being used.
One way to avoid this is to move the body of the init function into a separate .cpp file:
In IMidiEngine.h:
void Init(bool randomScore=true);
In IMidiEngine.cpp:
void IMidiEngine::Init(bool randomScore) {
pSamplwhk->pPianoRoll->Start();
}
I am completing my c++/CLI wrapper for the following native c++ class:
#ifndef __TV3DENGINE_H__
#define __TV3DENGINE_H__
#pragma once
#include "TV3DMoteur.h"
#include "Input.h"
#include "Area.h"
#include <vcclr.h>
class Engine3D
{
public:
CLTV3DMoteur* clTV3D;
CLInput* clInput;
CLArea* clArea;
CLGlobalVar * clGlobalVar;
Engine3D();
~Engine3D();
void Setup(HWND TVScreenHWND, string PathString);
void UpdateLoop();
void Cleanup();
bool AppStillIdle();
CLTV3DMoteur* GetTV3D();
CLInput* GetInput();
CLArea* GetArea();
CLGlobalVar * GetGlobalVar();
};
#endif
The actual constructor for Engine3D is :
Engine3D::Engine3D()
{
clTV3D = CLTV3DMoteur::getInstance();
clInput = CLInput::getInstance();
clArea = CLArea::getInstance();
clGlobalVar = CLGlobalVar::getInstance();
}
Here is the actual wrapper:
#ifndef __WRAPPER_H__
#define __WRAPPER_H__
#pragma once
#include "TV3DEngine.h"
#include <msclr\marshal_cppstd.h>
public ref class Engine3DWrapper {
Engine3D* m_nativeClass;
public:
Engine3DWrapper() { m_nativeClass = new Engine3D(); }
~Engine3DWrapper() { delete m_nativeClass; }
void Setup(System::IntPtr tvscreen, System::String^ AppPath) {
System::String^ managedPath = AppPath;
m_nativeClass->Setup((HWND)tvscreen.ToInt32(), msclr::interop::marshal_as<std::string>(managedPath));
}
void UpdateLoop() {
m_nativeClass->UpdateLoop();
}
void Cleanup() {
m_nativeClass->Cleanup();
}
bool AppStillIdle() {
return(m_nativeClass->AppStillIdle());
}
protected:
!Engine3DWrapper() { delete m_nativeClass; }
};
#endif
My question is how can I modifiy my Wrapper so I can have access to, exemple, Engine3DWrapper->clGlobalVar->BLABLABLA() where BLABLABLA would be all the different methods defined in the CLGlobalVar c++singleton?
I tried via this technique :
property String ^Name
{
String ^get()
{
return gcnew String(_stu->getName());
}
}
but that seems not possible since I need not to return a defined type.
thanks for your help.
Problem solved.
Here is the corrected Wrapper following Rufflewind suggestion:
#ifndef __WRAPPER_H__
#define __WRAPPER_H__
#pragma once
#include "TV3DEngine.h"
#include <msclr\marshal_cppstd.h>
public ref class Engine3DWrapper {
Engine3D* m_nativeClass;
public:
Engine3DWrapper(System::IntPtr tvscreen, System::String^ AppPath)
{
m_nativeClass = new Engine3D((HWND)tvscreen.ToInt32(), msclr::interop::marshal_as<std::string>(AppPath));
m_TV3D = m_nativeClass->GetTV3D();
m_Input = m_nativeClass->GetInput();
m_Area = m_nativeClass->GetArea();
m_GlobalVar = m_nativeClass->GetGlobalVar();
}
~Engine3DWrapper() {
delete m_nativeClass;
}
void UpdateLoop() {
m_nativeClass->UpdateLoop();
}
void Cleanup() {
m_nativeClass->Cleanup();
}
bool AppStillIdle() {
return(m_nativeClass->AppStillIdle());
}
CLTV3DMoteur* m_TV3D;
CLInput* m_Input;
CLArea* m_Area;
CLGlobalVar* m_GlobalVar;
protected:
!Engine3DWrapper() { delete m_nativeClass; }
};
#endif
using simple Get Method in the native class:
CLGlobalVar *Engine3D::GetGlobalVar()
{
clGlobalVar = CLGlobalVar::getInstance();
return(clGlobalVar);
}
Thanks for you help!