I would like to write an objective-C++ program in such a way that I could write:
class foo
{
public:
foo()
{
bar = "Hello world";
}
std::string bar;
};
Then (below in the same .mm file) I could create an instance of that class then do something like:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
foo* thisWontWork = new foo();
self.myLabel.text = foo.bar; //this doesn't work obviously
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
which would effectively change the text of label 'myLabel' to "Hello world"
This should work:
self.myLabel.text = #(foo->bar.c_str());
Which converts std::string to const char * to NSString.
But note: you are leaking foo, so:
#interface ViewController ()
{
foo _foo;
}
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
and use:
self.myLabel.text = #(_foo.bar.c_str());
Related
I know this has been asked a lot and I did implemented all I have created by looking around here and there.
I have all objective C files as .mm.
Also I can see in output console that "this = (a *) NULL" so the object used to call b(int x) function is null.
Here is my situation I am initialising c++ class from objective c++(.mm) class.
but I am getting BAD_ACCESS.
"a.cpp"
#include "a.h"
void a::b(int x) {
cout <<"hi";
c.push_back(x); // EXC_BAD_ACCESS error here.
cout<<c.size();
}
other files are as follow.
"a.h"
#ifndef __Cperiments__File__
#define __Cperiments__File__
#include <iostream>
#include <vector>
using namespace std;
class a {
public :
vector<int> c;
void b(int x);
};
#endif /* defined(__Cperiments__File__) */
AppDelegate.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#end
AppDelegate.mm
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc]
initWithNibName:nil bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "a.h"
#interface ViewController : UIViewController
{
a* objA;
}
-(id) init;
#property(readonly,assign) a* objA;
#end
ViewController.mm
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(id)init
{
if ((self = [super init]))
{
objA = new a();
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
objA->b(5);
}
#end
What else I am missing so that I can push some ints in vector.
Thanks
As pointed out by #borrrden in comments I never called init in appdelegate.mm.
replaced this line in appdelegate.mm
self.viewController = [[ViewController alloc]initWithNibName:nil bundle:nil];
with
self.viewController = [[ViewController alloc] init];
Thanks for quick help.
Schleife.h
#ifndef __CPlusPlusTest__Schleife__
#define __CPlusPlusTest__Schleife__
#include <iostream>
class Schleife;
#endif /* defined(__CPlusPlusTest__Schleife__) */
Schleife.cpp
#include "Schleife.h"
class Schleife
{
public:
int addition(int,int);
private:
int ergebnis;
};
int Schleife::addition(int a,int b)
{
ergebnis = a +b;
return ergebnis;
}
ViewController.h
#import <UIKit/UIKit.h>
#import "Schleife.h"
#interface ViewController : UIViewController
#end
ViewController.mm
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
Schleife *schleife = new Schleife();
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Whats Wrong?
I got the Error Message:
"ViewController.mm:22:31: Allocation of incomplete type 'Schleife'"
I don't understand what I did wrong. I want just implement C++ Code in my App. So I started with a easy example but it doesn't work...
Can you help me?
I know its maybe a easy Questions but I can't find the mistake...
Schleife.h should have this code instead of the cpp file
class Schleife
{
public:
int addition(int,int);
private:
int ergebnis;
};
you will also need to include #include "Schleife.h" in your ViewController.mm
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.
I am getting an EXC_BAD_ACCESS error in my contact listener code. Below is the code:
Main object class (GameObjects) through which all objects are subclassed:
GameObjects.h:
#import "cocos2d.h"
#import "CCNode.h"
#import "CCPhysicsSprite.h"
#import "Box2D.h"
#include <math.h>
#interface GameObjects : CCNode {
//b2Body* objectBody_;
}
-(b2Body*)getObjectBody;
-(void)objectsTouched:(GameObjects*)otherObject;
#end
GameObjects.mm (for now I just want to CCLOG to tell if it's working):
#import "GameObjects.h"
#implementation GameObjects
-(b2Body*)getObjectBody {
}
-(void)objectsTouched:(GameObjects*)otherObject {
CCLOG(#"it's working");
}
#end
ContactListenerTest.h:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "Box2D.h"
#import "Enemy.h"
#import "Sprite.h"
#import "GameObjects.h"
class ContactListenerTest : public b2ContactListener {
public:
b2World* world;
void BeginContact(b2Contact* contact);
};
ContactListenerTest.mm:
#import "ContactListenerTest.h"
void ContactListenerTest:: BeginContact(b2Contact *contact)
{
b2Fixture *fixtureA = contact->GetFixtureA();
b2Fixture *fixtureB = contact->GetFixtureB();
b2Body *fixtureABody = fixtureA->GetBody();
b2Body *fixtureBBody = fixtureB->GetBody();
GameObjects* spriteObject = (GameObjects*)fixtureABody->GetUserData();
GameObjects* spriteObject2 = (GameObjects*)fixtureBBody->GetUserData();
[spriteObject objectsTouched:spriteObject2];
[spriteObject2 objectsTouched:spriteObject];
}
When I get the EXC_BAD_ACCESS error the following is printed in the console:
-[Enemy objectsTouched:]: unrecognized selector sent to instance 0x8558840
Enemy is one of the subclasses of GameObjects.
Verify that the userdata object actually is of GameObjects class:
NSAssert1([spriteObject isKindOfClass:[GameObjects class]],
#"userdata %# not a game object", spriteObject);
NSAssert1([spriteObject2 isKindOfClass:[GameObjects class]],
#"userdata 2 %# not a game object", spriteObject2);
When you initialize the GameObject you should make sure that the UserData of the created body points to your GameObject. Something like this:
objectBody_->SetUserData(self);
I have class called "HelloWorld.m" and another class called "Person.m". I have declared Person instance in the HelloWorld.m class as follows:
Person *person;
Now, when the user touches the screen I fire the following method:
[person foo];
But I get the error saying invalid selector sent.
NOTE: Person class inherits from the CCSprite class. What am I doing wrong?
Person.h:
-(void) foo;
Person.m:
-(void) foo
{
NSLog(#"foo called!");
}
UPDATE 1: In the HelloWorld.h and HelloWorld.m I have declarated person as a property. Here is the call to the person.foo method.
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.person foo];
}
HelloWorld.h:
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "Person.h"
// Importing Chipmunk headers
#import "chipmunk.h"
// HelloWorld Layer
#interface HelloWorld : CCLayer
{
cpSpace *space;
Person *person;
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
-(void) step: (ccTime) dt;
-(void) addNewSpriteX:(float)x y:(float)y;
#property (nonatomic,retain) Person *person;
#end
Did you import the Person header into the top of the HelloWorld file?
#import "Person.h"
Did you initialise the person pointer?
person = [[Person alloc] init];
Does the Person class have a foo method?