Running into issues trying to mix c++ and objective-c when building cocoa app using Xcode4.
The issue is when I use NSTimer to call handleFrame function, which calls a virtual function of a class.
Here is what i am trying to do:
1. Create a monitor;
2. Create a handler;
3. Assign handler to monitor (init function)
4. Call monitor->update() that is expected to call handler's virtual method.
5. Code works as expected in applicationDidFinishLaunching function, however NSTimer is causing EXC_BAD_ACCESS exception in handleFrame.
//
// AppDelegate.h
// Concept5
//
#import <Cocoa/Cocoa.h>
#include "monitor.h"
#include "Derived.h"
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
Monitor *monitor;`enter code here`
NSTimer *gameTimer;
}
#property (assign) IBOutlet NSWindow *window;
- (void)handleFrame:(NSTimer *)timer;
#end
AppDelegate implementation (.mm)
//
// AppDelegate.mm
// Concept5
//
#import "AppDelegate.h"
#implementation AppDelegate
- (void)dealloc
{
[super dealloc];
}
- (id) init {
self = [super init];
if(self) {
monitor = new Monitor();
}
return self;
}
- (void)handleFrame:(NSTimer *)timer {
monitor->update();
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
Derived derived;
monitor->init(derived);
monitor->update();
gameTimer = [[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(handleFrame:)
userInfo:nil
repeats:YES] retain];
monitor->update();
}
#end
//
// Monitor.cpp
// Concept5
//
#include "Monitor.h"
void Monitor::init (Base& handler)
{
_handler = &handler;
}
void Monitor::update()
{
if (_handler != NULL)
{
_handler->speak(); // <-- EXC_BAD_ACCESS exception.
}
}
//
// Monitor.h
// Concept5
#ifndef __Concept5__Monitor__
#define __Concept5__Monitor__
#include <iostream>
#include "Base.h"
class Monitor
{
private:
Base* _handler;
public:
void init (Base& handler);
void update();
};
#endif /* defined(__Concept5__Monitor__) */
//
// Base.cpp
// Concept5
#include "Base.h"
void Base::speak()
{
std::cout << "Base speaks" << std::endl;
}
//
// Base.h
// Concept5
#ifndef __Concept5__Base__
#define __Concept5__Base__
#include <iostream>
class Base
{
public:
virtual void speak();
};
#endif /* defined(__Concept5__Base__) */
//
// Derived.cpp
// Concept5
#include "Derived.h"
void Derived::speak()
{
std::cout << "Derived speaks" << std::endl;
}
//
// Derived.h
// Concept5
//
#ifndef __Concept5__Derived__
#define __Concept5__Derived__
#include <iostream>
#include "Base.h"
class Derived : public Base
{
public:
void speak();
};
#endif /* defined(__Concept5__Derived__) */
I have never used Objective-C, but the following looks like an issue:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Derived derived;
monitor->init(derived);
//....
}
Since Derived is a local variable, the scope will not go beyond the applicationDidFinishLaunching function. Thus calling init() (which takes a pointer), will be holding onto an invalid object when the above function returns.
If this were C++, the solution is to make sure the lifetime of the object is sufficient. The usual solutions are:
1) Make the object global, or
2) Create the object dynamically using new, or
3) Create a smart pointer (probably std::shared_ptr) and use that instead of raw pointers.
I'm not an Objective-C expert, but EXC_BAD_ACCESS mean you are trying to access something with a bad pointer, likely a nil pointer.
Since your timer is calling an INSTANCE method in stead of a CLASS method on a Monitor instance, you better have a monitor instance when your timer fires. My guess is that you don't. If I was more of an Objective-C person, I could probably look at your code & see this, but as it is I would have to run your code to tell. But I'd bet that is what is wrong.
That all being said, it is a risky idea to call timers with instance methods, unless you are absolutely sure the instance will still be around & you know what you're doing. It is safer to only call class methods on a timer.
Related
I am kind of new to C++ (and StackOverflow). I am trying to get something to work, but I have some #include problems.
I want to call a callback I made (from here), but I am struggling to do this.
This is my code so far. When I include child.hpp in the someclass.hpp file (because it needs information about Child for Callback<Child>), it has a looped include and the compiler crashes.
I have read about forward declarations (would be class Child; in the someclass.hpp file), and after trying I figured out this works, but I also read different opinions about this.
I have all .hpp files guarded with #ifndef CLASSNAME #define CLASSNAME ... #endif
Do I need to change my entire design, or what is the best option in my case?
base.hpp
#include "someclass.hpp"
class Base
{
protected:
unique_ptr<SomeClass> someClass;
};
base.cpp
#include "base.hpp"
Base::Base()
{
this->someClass = make_unique<SomeClass>();
}
child.hpp
#include "base.hpp"
class Child : public Base
{
public:
void callbackFunction(std::string data);
unique_ptr<Callback<Child>> callback;
};
child.cpp
#include "child.hpp"
void Child::callbackFunction(std::string data)
{
/*does something*/
}
Child::Child()
{
this->callback = make_unique<Callback<Child>>(this, &Child::callbackFunction);
//I can call this->callback->call(data); here without problems
this->someClass->setCallback(this->callback);
//^^^^^^^^^^^^^^^ == base.someClass
}
someclass.hpp
#include "child.hpp" // < does crash compiler due to loop
//> someclass.hpp uses child.hpp
//> child.hpp uses base.hpp
//> base.hpp uses someclass.hpp
// and thus loop
class SomeClass
{
public:
void someFunction(std::string data);
void setCallback(unique_ptr<Callback<Child>> callback);
unique_ptr<Callback<Child>> callbackInstance;
};
someclass.cpp
//not 100% sure about the type of this parameter
void setCallback(unique_ptr<Callback<Child>> callback)
{
this->callbackInstance = callback;
}
void SomeClass::someFunction(std::string data)
{
//here I want to call this "Child::callbackFunction" which should go like "this->callbackInstance->call(data)" ?
}
also in someclass.hpp
template<class T>
class Callback
{
public:
Callback(T* instance, void (T::*function)(std::string))
{
this->callbackInstance = instance;
this->callback = function;
}
void call(std::string data)
{
(callbackInstance->*callback)(data);
}
private:
T *callbackInstance;
void (T::*callback)(std::string);
};
To solve the mentioned error("expected class-name before '{' token on child.hpp") you should remove the #include "someclass.hpp" from base.hpp and replace it with a forward declaration for class SomeClass as shown below.
base.hpp
#ifndef BASE_H
#define BASE_H
//NO NEED TO INCLUDE someclass.hpp
#include <memory>
class SomeClass;//FORWARD DECLARE SomeClass
class Base
{
std::unique_ptr<SomeClass> someClass;
public:
//add declaration for default constructor
Base();
};
#endif
base.cpp
#include "base.hpp"
#include "someclass.hpp"
//other things here
Base::Base()
{
this->someClass = std::make_unique<SomeClass>();
}
child.hpp
#ifndef CHILD_H
#define CHILD_H
#include "base.hpp"
#include <memory>
#include "someclass.hpp"
class Child : public Base
{
public:
void callbackFunction(std::string data);
std::unique_ptr<Callback<Child>> callback;
//add declaration for default constrcutor
Child();
};
#endif
child.cpp
#include "child.hpp"
void Child::callbackFunction(std::string data){
/*does something*/
}
Child::Child()
{
this->callback = std::make_unique<Callback<Child>>(this, &Child::callbackFunction);
//I can call this->callback->call(data); here without problems
}
someclass.hpp
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include <string>
//REMOVED include child.hpp from here
class SomeClass
{
public:
void someFunction(std::string data);
//I think I need an instance of Callback<Child> here?
};
template<class T>
class Callback
{
public:
Callback(T* instance, void (T::*function)(std::string))
{
this->callbackInstance = instance;
this->callback = function;
}
void call(std::string data)
{
(callbackInstance->*callback)(data);
}
private:
T *callbackInstance;
void (T::*callback)(std::string);
};
#endif
someclass.cpp
#include "someclass.hpp"
void SomeClass::someFunction(std::string data)
{
//here I want to call this "Child::callbackFunction" which should go like "this->callbackInstance->call(data)" ?
}
The above program compiles and executes successfully as can be seen here.
Summary
Some of the changes that i made are listed below:
Removed unnecessary includes
Added declarations for default constructor in child.hpp and base.hpp
Added include guards in all headers.
For a c++ application which I'm currently being busy to develop, I have several classes which I need to access through my entire code, without creating a new object
So searching I have found that one of methods that can be used is with the extern linkage specifier.
I would like to know what is best way to use this extern method, I wrote a little sample code
classone.h
#ifndef CLASSONE_H
#define CLASSONE_H
class ClassOne
{
public:
ClassOne();
void showClassOneInt();
private:
int m_classOneInt;
};
extern ClassOne *classOne;
---------------------------------------
classone.cpp
#include "classone.h"
#include <QDebug>
ClassOne *classOne;
ClassOne::ClassOne()
{
m_classOneInt = 1;
}
void ClassOne::showClassOneInt()
{
qDebug() << "ClassOneInt: " << m_classOneInt;
}
---------------------------------------
classtwo.h
#ifndef CLASSTWO_H
#define CLASSTWO_H
class ClassTwo
{
public:
ClassTwo();
void showClassTwoInt();
private:
int m_classTwoInt;
};
#endif // CLASSTWO_H
---------------------------------------
classtwo.cpp
#include "classtwo.h"
#include <QDebug>
ClassTwo::ClassTwo()
{
m_classTwoInt = 2;
}
void ClassTwo::showClassTwoInt()
{
qDebug() << "ClassTwoInt: " << m_classTwoInt;
}
---------------------------------------
classthree.h
#ifndef CLASSTHREE_H
#define CLASSTHREE_H
class ClassThree
{
public:
ClassThree();
void showClassThreeInt();
private:
int m_classThreeInt;
};
#endif // CLASSTHREE_H
---------------------------------------
classthree.cpp
#include "classthree.h"
#include <QDebug>
ClassThree::ClassThree()
{
m_classThreeInt = 3;
}
void ClassThree::showClassThreeInt()
{
qDebug() << "ClassThreeInit: " << m_classThreeInt;
}
---------------------------------------
classtest.cpp
#include "classtest.h"
#include "classone.h"
#include "classtwo.h"
#include "classthree.h"
//Class one pointer already in header
//Class two
extern ClassTwo *classTwo;
//Class three
extern ClassThree *classThree;
ClassTest::ClassTest()
{
//Execute class one
classOne->showClassOneInt();
//Execute class two
classTwo->showClassTwoInt();
//Execute class three
classThree->showClassThreeInt();
}
---------------------------------------
main.cpp
#include <QCoreApplication>
#include "classone.h"
#include "classtwo.h"
#include "classthree.h"
#include "classtest.h"
//Class one pointer already in header file
//Class two pointer
ClassTwo *classTwo;
//Class three pointer
ClassThree *classThree;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//Create object for class one
classOne = new ClassOne;
//Create object for class two
classTwo = new ClassTwo;
//Create object for class three
ClassThree three;
classThree = &three;
//Create a classTest object
ClassTest test;
return a.exec();
}
Please could you tell me what is the best way, thanks for you help.
The best way is to not do it and instead use dependency injection.
If you choose to do it anyway, you should at least use getter/factory functions (i.e. ClassOne &getClassOne())) so you can:
be sure random code can't change the objects and
handle order of construction implicitly by constructing on first use (sometimes appropriate, sometimes not).
Having a global state is generally not a great idea, seek to eliminate it.
If that cannot be done, try the singleton pattern.
class Singleton
{
Singleton(); //keep constructors private to avoid creation by others
static Singleton inst;
public:
static Singleton& Instance() {return inst;}
};
Singleton Singleton::inst;
I am trying to create simple application with gtkmm but I'm having some problem.
Here's how it looks now:
Here's the code to generate it:
MyWindow.h:
#ifndef MYWINDOW_H_
#define MYWINDOW_H_
#include <gtkmm/window.h>
#include <gtkmm/frame.h>
#include "MyDrawingArea.h"
class MyWindow :public Gtk::Window {
public:
MyWindow();
virtual ~MyWindow() {}
private:
MyDrawingArea drawing_area;
};
#endif /* MYWINDOW_H_ */
MyWindow.cpp:
#include "MyWindow.h"
MyWindow::MyWindow() : drawing_area("Drawing area") {
set_title("My app");
set_border_width(10);
add(drawing_area);
drawing_area.draw_stuff_in_area();
show_all_children();
}
MyDrawingArea.h:
#ifndef MYDRAWINGAREA_H_
#define MYDRAWINGAREA_H_
#include <gtkmm/frame.h>
#include <gtkmm/drawingarea.h>
class MyDrawingArea : public Gtk::Frame {
public:
MyDrawingArea(const Glib::ustring& title);
virtual ~MyDrawingArea() {}
void draw_stuff_in_area();
private:
Gtk::DrawingArea area;
};
#endif /* MYDRAWINGAREA_H_ */
MyDrawingArea.cpp:
#include "MyDrawingArea.h"
#include <iostream>
#include <gtkmm/window.h>
MyDrawingArea::MyDrawingArea(const Glib::ustring& title) : Gtk::Frame(title) {
set_border_width(20);
add(area);
area.set_size_request(300, 250);
}
void MyDrawingArea::draw_stuff_in_area() {
Cairo::RefPtr<Cairo::Context> cr = area.get_window()->create_cairo_context(); // program crashes here!
// draw stuff with 'cr' here...
}
As the comment suggests, the program crashes when I try to create a Cairo::Context, though I don't think the Cairo::Context creation is the problem: Every dereferencing to the object returned by my_area.get_window() crashes the program!
Anyone know what's causing the problem?
Hi did you check the return value of area.get_window() because documentation says
Returns the widget’s window if it is realized, 0 otherwise.
I need to create a thread to run the Networking portion of my game. I would prefer to use SFML threads as my compiler doesn't yet support C++11 threads. However the class which contains the thread is created with make_shared(). Here is the code:
Game.cpp (not all the code just the declaration of GameScreen)
std::shared_ptr<Screen> Game::screen = std::make_shared<GameScreen>();
Screen is just a base class containing pure virtual functions. You should be able to figure out which ones are virtual based off the override keywords.
GameScreen.h
#ifndef GAMESCREEN_H
#define GAMESCREEN_H
#include <SFML/Graphics.hpp>
#include "Events.h"
#include "Screen.h"
#include "Map.h"
#include "Network.h"
class GameScreen : public Screen
{
public:
GameScreen();
void handleInput(sf::RenderWindow&) override;
void update(sf::RenderWindow&, sf::View&) override;
void render(sf::RenderWindow&) override;
private:
Map m_map;
Network network;
Events eventManager;
sf::Thread networkThread;
};
#endif // GAMESCREEN_H
GameScreen.cpp
#include <memory>
#include <iostream>
#include "GameScreen.h"
#include "Game.h"
GameScreen::GameScreen()
: networkThread(network.receive(eventManager))
{
network.Connect();
}
void GameScreen::handleInput(sf::RenderWindow& window)
{
/*Code*/
}
void GameScreen::update(sf::RenderWindow& window, sf::View& view)
{
/*Code*/
}
void GameScreen::render(sf::RenderWindow& window)
{
/*Code*/
}
Network.cpp (receive function only)
void Network::Recieve(Events& eManager)
{
sf::Packet m_rPacket;
m_socket.receive(m_rPacket, m_serverIP, port);
m_rPacket >> /*Data*/
eManager.addEvent(tmp);
}
You can use this in the constructor's initialization list:
MyClass::MyClass()
: AClass(&MyFunction(*this))
{
/*do stuff*/
}
However, this doesn't make sense in your example, because you are trying to pass a pointer to MyFunction (or its non-existent return value) to AClass(), and you can't quality a pointer with parameters. You can only pass parameters to MyFunction() when actually calling MyFunction(). Are you sure you don't actually mean something more like this instead:
MyClass::MyClass()
: AClass()
{
/*do stuff*/
MyFunction(*this);
}
Without seeing what AClass() actually is, or what it expects as input, it is difficult to know for sure what you are trying to do.
Update clearly you have not read the SFML documentation or SFML Tutorial on threading. The Thread constructor takes a pointer to a function/method as one input parameter, and an optional input value for the function/method as a separate parameter. Try this instead:
class MyClass : public sf::Thread
{
private:
static void MyFunction(MyClass &cls);
public:
MyClass();
};
MyClass::MyClass()
: sf::Thread(&MyClass::MyFunction, *this)
{
/*do stuff*/
}
void MyClass::MyFunction(MyClass &cls)
{
/*do stuff with 'cls'*/
}
Or this, as you can use a non-static class method with an SFML thread:
class MyClass : public sf::Thread
{
private:
void MyFunction();
public:
MyClass();
};
MyClass::MyClass()
: sf::Thread(&MyClass::MyFunction, *this)
{
/*do stuff*/
}
void MyClass::MyFunction()
{
/*do stuff with 'this'*/
}
Update: based on your new code, you are still not even close to constructing the sf::Thread object correctly (did you read the documentation/tutorial I linked to?). Also, your thread needs access to multiple objects owned by GameScreen, so you can't pass them all to the sf::Thread constructor. You need to do something more like this instead:
class GameScreen : public Screen
{
public:
GameScreen();
...
private:
...
Network network;
Events eventManager;
sf::Thread networkThread;
void networkThreadFunc();
};
GameScreen::GameScreen()
: networkThread(&GameScreen::networkThreadFunc, *this)
{
network.Connect();
}
void GameScreen::networkThreadFunc()
{
network.Receive(eventManager);
}
How can I call an Objective C instance method from a c++ class? In TestApp.cpp I would like to call updateUI in TestDelegate.mm
TestDelegate.h
#include "cinder/app/CinderView.h"
#include "TestApp.h"
#import <Cocoa/Cocoa.h>
#interface TestDelegate : NSObject <NSApplicationDelegate>
{
IBOutlet CinderView *cinderView;
IBOutlet NSWindow *window;
TestApp *mApp;
}
#property (assign) IBOutlet NSWindow *window;
- (IBAction)subdivisionSliderChanged:(id)sender;
- (void)updateUI;
#end
TestDelegate.mm
#include "cinder/Cinder.h"
#import "TestDelegate.h"
#implementation TestDelegate
#synthesize window;
- (void)dealloc
{
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
mApp = new TestApp;
mApp->prepareLaunch();
mApp->setupCinderView( cinderView, cinder::app::RendererGl::create() );
mApp->launch();
}
- (void)updateUI
{
//Set new values...
}
#end
TestApp.h
#pragma once
#include "cinder/app/AppCocoaView.h"
class TestApp : public cinder::app::AppCocoaView {
public:
void setup();
void draw();
};
TestApp.cpp
#include "TestApp.h"
#include "cinder/gl/gl.h"
using namespace ci;
using namespace ci::app;
void TestApp::setup()
{
//Set values
//Call updateUI method in TestDelegate.mm
}
void TestApp::draw()
{
}
Something like the following ought to work:
TestDelegate.mm
#include "cinder/Cinder.h"
#import "TestDelegate.h"
#implementation TestDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// mApp = new TestApp;
// mApp->prepareLaunch();
// mApp->setupCinderView( cinderView, cinder::app::RendererGl::create() );
// add the following line
mApp->m_TestDelegate = self;
// mApp->launch();
}
#end
TestApp.h
#pragma once
#include "cinder/app/AppCocoaView.h"
#class TestDelegate;
class TestApp : public cinder::app::AppCocoaView {
public:
void setup();
void draw();
TestDelegate *m_TestDelegate;
};
TestApp.cpp -> renamed to TestApp.mm
#include "TestApp.h"
#include "cinder/gl/gl.h"
#import "TestDelegate.h"
using namespace ci;
using namespace ci::app;
void TestApp::setup()
{
//Set values
//Call updateUI method in TestDelegate.mm
[this->m_TestDelegate updateUI];
}
Note: this code was written in a browser, and the Objective-C++ stuff I've done doesn't use ARC, so if it gives any warnings/errors, let me know and I'll update the code accordingly.
To call an instance method, you need an instance. Once your C++ code has a pointer to an instance of the class, you can just change the file to Objective-C++ and send a message like normal.