I've one application and two lib files. Application initialize a class object which need to pass to another class which is in the library. How can i do that? Here is what i did but it just crash
mainClass.h
#interface mainUIDelegate: NSObject<UIApplicationDelegate>
{
bla bla...
myCppClass myCppObject;
}
mainClass.mm
-(void)viewDidLoad{
myCppObject = new myCppClass();
}
-(void)initObject:(id)sender
{
prefTableViewController *prefs = [[prefTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
prefs.myCppObject = myCppObject;
}
library 1 (myCppClass.h) (with cpp class object)
class myCppClass{
int a;
}myCppClass;
library 2 (prefTableViewUI.h)
#interface prefTableViewController:UITableViewController{
myCppClass myCppObject;
}
#property (nonatomic, assign) myCppClass myCppObject;
Can someone please let me know how can i pass such object? I've just a month experience in object C.
Indeed more information is needed on what/where exactly crash. Not knowing how your class is defined, I'd say the property looks suspicious. You want to try to create a method first, say -[prefTableViewController setMyCppObject:] with the argument type being myCppClass*, and then implement the method as myCppObject = *argument.
(One sideway suggestion, though purely stylistic matter: Upper-casing the first letter of your Objective-C class name will help tell which is which)
I resolved this, the problem was lying in sythensizing the object. I had forgot to synthesize the object.
Related
I want to declare a C++ property inside my Objective-C class.
What kind of attributes should I set it to? It seems that strong or retain will lead to an error saying that it is not an object.
How could I manage its memory properly?
You are right, the property cannot be weak, strong, or retained; for that it would have to be a pointer to an Objective-C object. If you don't use any attributes on a C++ property, it will default to unsafe_unretained,assign,atomic.
A few other things to consider, assuming the Objective-C(++) object controls the lifetime of the C++ property:
Because you can't do much with a C++ object in Objective-C, the
property is mostly useful in Objective-C++ code, where you can mix
Objective-C and C++.
Because you have to manage the property's memory on your own, you
need a custom setter.
Because the property defaults to atomic, you need to use
synchronization in the setter and need a custom getter, too. You
could declare it nonatomic, in which case you would not need to
synchronize and would not need a custom getter.
You can implement dealloc to ensure the C++ object is freed when
the Objective-C++ object goes away.
Here's some useful documentation from Apple: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html.
And here is a quick example. Let's say the C++ class you are using for the property is called MyCPP. In a header you could have:
#interface ClassOCPP : NSObject
// This property can only be used in Objective-C++ code
#ifdef __cplusplus
#property /*(unsafe_unretained,assign,atomic)*/ MyCPP * myCPP;
#endif
// Other stuff may be usable in regular Objective-C code.
#end
Implementation could be as follows (in a .mm file; remember, it's Objective-C++):
#implementation ClassOCPP
{
MyCPP * _myCPP;
}
-(id)init {
self = [super init];
_myCPP = NULL;
return self;
}
-(void)setMyCPP:(MyCPP*)newVal {
#synchronized(self) {
delete _myCPP; // it's OK to delete a NULL pointer
_myCPP = newVal;
}
}
-(MyCPP*)myCPP {
return _myCPP;
}
-(void)dealloc {
puts("De-allocating ClassOCPP.");
delete _myCPP;
}
#end
IIRC, you need to manage it like any other C++ object, so just use assign as the attribute, and you should be good.
Right now my OS X 10.9 project is set up with a GUI in Objective-C and all the processing in a C++ class. This doesn't seem like the best way, but this was given to me and I have to work with these constraints. I currently have a NSSlider in the Cocoa GUI. I want to be able to have this NSSlider control a variable x in the C++ class.
Currently the tolerance bar is working when I run the program (working meaning it's continuously updating its value as per my sliding).
Header for NSSlider (Slider.h):
#interface Slider : NSObject {
#private
__weak IBOutlet NSTextField *sliderValue;
__weak IBOutlet NSSlider *slider;
}
- (IBAction)updateSliderValue:(id)sender;
#end
Implementation for the NSSlider (Slider.mm):
#import "Slider.h" // The NSSlider object
#import "CMain.h" // The C++ class that does all the processing (not sure if this is the way to include a C++ interface in an Objective-C++ class or if this will allow me to call its methods)
#implementation Slider
-(void) awakeFromNib {
[slider setIntValue:40];
[sliderValue setIntValue:[slider intValue]];
}
- (IBAction)updateSliderValue:(id)sender {
[sliderValue setIntValue:[slider intValue]];
// Here is where I'd think that if I have a setValueofX(int number) method in the C++ class
// I could call this somehow using objective-C++. I don't know if I can or how to call this method here
}
Here is the relevant snippet from Main.h:
class CMain(){
public:
CMain();
void setValueofX(int number);
int getValueofX();
private:
int x;
};
How do I include CMain.h in the Objective-C++ (which, the .h file or .mm file? and how?) such that it would allow me to call the methods in CMain.h? How would I phrase the method call in Objective-C to set x's value using the setValueofX(sliderValue)?
Please let me know if more information is needed! Any help or thoughts are appreciated!
Thanks!
The code for calling the setter is the same as it would be in C++. However, you'd need a pointer to the CMain object to be able to call the method on it. I don't know where that object currently resides. If there is no object yet in another object, you probably want to create one, which you can by just declaring an instance variable CMain myCMain; and then calling myCMain.setValueOfX( [slider intValue] ); in updateSliderValue:.
As to where to include the C++ class, it's really your choice. However, if you use any C++ in your header, it will take a bunch of careful extra work to include it from plain .m files. So in general I try to stick to plain C and ObjC in the header, and only use C++ in the .mm file. You can use a class extension (sometimes called "class continuation" as well) to declare additional ivars in your .mm file to keep them out of the header.
If you want more info about ObjC++, I answered in detail on another post: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link? and that also links to a Podcast I was a guest on where I talk about a lot of the details and tricks for integrating ObjC and C++.
Aside: I hope these are not actual names and comments you're using. Never have an ObjC class without a prefix (3 letters, Apple stated they reserve all 2-letter prefixes for their own use, and they've used un-prefixed internal class names in the past which broke some peoples' programs). Also, "Slider" is a bad name, as NSSlider is the actual slider, and this sounds like it should be a subclass. You really want to call this an ISTSliderController or whatever.
I found a solution by noting that there was an existing wrapper class CWrapper.h and it was an objective-C++ implementation class CWrapper.mm. There was a CMain variable instantiated as cmain. I made a getter method for x and I simply created a static method in the wrapper class + (void) passX:(int) number; that I called in the slider class. I chose a static method because this for this application, this value will never have to be different between objects. I hope I made the right choice here!
See code changes below:
I added this to the Slider.h file.
- (int)X;
I added the getter and [CWrapper passX:[self getX]]; to the updateSliderValue method in the Slider.mm file.
- (int)X {
return [slider intValue];
}
- (IBAction)updateSliderValue:(id)sender {
[sliderValue setIntValue:[slider intValue]];
[CWrapper passX:[self getX]];
}
This is the code I added to CWrapper.h.
+ (void) passX:(int) number;
This is the code I added to CWrapper.mm.
+ (void) passX:(int)num
{
cmain.setValueofX(num);
}
Here's an all objective-c and objective-c++ answer:
CMain.h:
#ifndef Testing_CMain_h
#define Testing_CMain_h
#interface CCMain : NSObject
-(CCMain*) init;
-(void) dealloc;
-(void)setValueofX:(int)number;
-(int)getValueofX;
#end
#endif
CMain.mm:
#import <Foundation/Foundation.h>
#import "CMain.h"
class CMain {
private:
int x;
public:
CMain() : x(0) {}
void setValueofX(int number) {x = number;}
int getValueofX() const {return x;}
};
#interface CCMain ()
#property (nonatomic, assign) CMain* inst;
#end
#implementation CCMain
-(CCMain*) init
{
if (!_inst)
{
_inst = new CMain();
}
return self;
}
-(void) dealloc
{
delete _inst;
_inst = nil;
}
-(void)setValueofX:(int)number
{
_inst->setValueofX(number);
}
-(int)getValueofX
{
return _inst->getValueofX();
}
#end
and if you want to use C-style functions then:
setValueofX(cmain_instance, value);
int val = getValueofX(cmain_instance);
And this works because a C++ class function in C is the same as:
void CMain::MyFunc(int X);
//vs..
void MyFunc(CMain* inst, int X);
Both are the exact same thing.
As I know, c++ object in iOS is allocated in the stack memory. Now I have to add the c++ object into a NSArray, however NSArray cannot store c++ objects directly.
The question is how could I store a c++ object in a NSArray and let the NSArray take ownership of the c++ object so that I could use the c++ object whenever I want.
Thanks for any help!
=========EDIT========
Here are some code snippet:
std::list<ImageTextContent> msgs = body->getMsgs();
std::list<ImageTextContent>::iterator itmsgs0;
for(itmsgs0 = msgs.begin();itmsgs0 != msgs.end();itmsgs0++)
{
ImageTextContent *tmpmsgs = &(*itmsgs0);
ImageTextContentWrapper *itc = [[ImageTextContentWrapper alloc] initWithImageTextContent:tmpmsgs];
[self.dataSource addObject:itc];
}
[self.tableview reloadData];
the cellForRow method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
........
ImageTextContentWrapper *itc = (ImageTextContentWrapper *)[_dataSource objectAtIndex:indextPath.row];
NSString *title = [NSString stringWithCString:(itc.imageTextContent->getTitle()).c_str() encoding:NSUTF8StringEncoding];
cell.titleLabel.text = title;
........
}
ImageTextContentWrapper class:
#interface ImageTextContentWrapper : NSObject
#property (nonatomic, assign) ImageTextContent *imageTextContent;
- (id)initWithImageTextContent:(ImageTextContent *)imageTextContent;
#end
#implementation ImageTextContentWrapper
- (id)initWithImageTextContent:(ImageTextContent *)imageTextContent
{
if (self = [super init])
{
self.imageTextContent = imageTextContent;
}
return self;
}
#end
Create an Objective-C class owning your C++ object, and store objects of this class in NSArray.
A small code example how to wrap a C++ object in a Objective-C class:
For a C++ class CPP which could look like
class CPP {
public:
std::string aName;
CPP(std::string aName) : aName(aName) { }
};
you can create a Objective-C wrapper class ObjectiveC:
// ObjectiveC.h
#interface ObjectiveC : NSObject
{
CPP *cpp;
}
- (id)initWithString:(NSString*)string;
- (void)print;
#end
//ObjectiveC.mm <- this .mm tells Xcode to use the right compiler
#import "ObjectiveC.h"
#implementation ObjectiveC
- (id)initWithString:(NSString*)string
{
self = [super init];
if (self)
{
cpp = new CPP([string UTF8String]);
}
return self;
}
- (void)print
{
NSLog(#"%s", cpp->aName.c_str());
}
#end
Now you can create a NSArray containing indirectly containing the C++ objects:
// main.mm for example (.m -> .mm !)
ObjectiveC *oc1 = [[ObjectiveC alloc] initWithString:#"oc1"];
ObjectiveC *oc2 = [[ObjectiveC alloc] initWithString:#"oc2"];
ObjectiveC *oc3 = [[ObjectiveC alloc] initWithString:#"oc3"];
NSArray *array = [[NSArray alloc] initWithObjects:oc1, oc2, oc3, nil];
for (ObjectiveC *oc in array) {
[oc print];
}
A small remark: You have to change all implementation files containing and interacting with this wrapper files from .m to .mm. The second option is to change the compiler in the Xcode settings.
You're off the mark a little. There are two ways to create C++ objects. On the stack (by declaring it as a local, non-pointer variable) or on the heap (e.g. using operator new or by declaring it as a non-pointer instance variable in an ObjC object).
If you actually have one on the stack, there is no way to (safely) reference it from an ObjC class. In ObjC, all objects are on the heap, so everyone who retains it is guaranteed that it will stay around even if the function in which it is declared returns. And the last one who releases it causes its memory to actually be freed.
You can't give that guarantee with stack objects, as they must go away the moment the function in which they are a local variable returns.
But if you could create your C++ object with operator new and your code would still work, instead of a stack object, then you can just create an ObjC class in an ObjC++ file (.mm suffix instead of straight .m), and put that in an array. If you want to learn more about ObjC++, I recommend you listen to my guest spot on the NSBrief podcast, where I talk about ObjC++ in detail.
Alternately, what reason prevents you from just putting your C++ object in a std::vector instead of an NSArray? What are you hoping to use this NSArray full of C++ objects for?
PS - For completeness' sake, let me also mention that there is +NSNumber numberWithNonretainedPointer: (or maybe it was "unretained") which you could use as a pre-made object for keeping a pointer in an array, but this is not recommended, as it does not call delete on the pointer when it is released, so you have to be very careful or you'll leak C++ objects. Better to make your own class.
I have a C++ class method where i need to call the "detachNewThreadSelector" method with all the parameters.
Here lies the problem, as my class is not objective C i don't have a self pointer. Also i don't see how i will be able to call a class method from the method that i will set as selector.
Please do ask if my question is not clear, i am not from a english speaking country.
Here is some code.
ALuint AudioController::PlayStream(const string& asset)
{
//attach to a thread
[NSThread detachNewThreadSelector:(SEL)selector toTarget:(id)selfwithObject:(id)argument]
}
void AudioController::RotateThread(const string& soundKey)
{
}
As you can see how do i pass the RotateThread method as a selector to the "detachNewThreadSelector" and also where do i get the self pointer.
Any help much appreciated.
Thanks
You can't do this. It isn't as a simple as "Where do I get the self pointer?" The actual question is, "Where do I get something that can respond to messages?" Because a C++ class can't.
Objective-C classes, objects and methods are completely different things from C++ classes, objects and methods. The fact that the two languages use the same terminology and use the things for similar purposes confuses a lot of people, but to be clear: They are totally different things that work in very different ways in the two languages. Case in point: C++ methods are simply called rather than dispatched based on a selector like Objective-C methods. And C++ classes aren't even objects.
You have two real options here:
Create an Objective-C class that has the behavior you want.
Use a C++ concurrency solution.
you may not use c++ object in this manner (as an argument to this NSThread method). if your case is simple (read: few interfaces declared), then you can create a utility (objc) class to handle the message, and to then pass the argument back to the AudioController instance. illustration:
(non-compiled pseudo code follows)
namespace pseudo_object {
template <typename> class reference_counted;
}
#interface MONAudioControllerWorker : NSObject
{
pseudo_object::reference_counted<AudioController> audioController_;
std::string asset_;
}
+ (MONAudioControllerWorker *)newMONAudioControllerWorkerWithAudioController:(pseudo_object::reference_counted<AudioController>&)audioController asset:(const std::string&)asset;
- (void)secondaryWorker;
#end
#implementation MONAudioControllerWorker
+ (MONAudioControllerWorker *)newMONAudioControllerWorkerWithAudioController:(pseudo_object::reference_counted<AudioController>&)audioController asset:(const std::string&)asset
{
/* ... */
}
- (void)secondaryWorker
{
NSAutoreleasePool * pool([NSAutoreleasePool new]);
audioController_->RotateThread(asset_);
[pool release];
}
#end
/* static */
ALuint AudioController::PlayStream(pseudo_object::reference_counted<AudioController>& This, const string& asset)
{
/* attach to a thread */
MONAudioControllerWorker * controller = [MONAudioControllerWorker newMONAudioControllerWorkerWithAudioController:This asset:asset];
[NSThread detachNewThreadSelector:#selector(secondaryWorker) toTarget:controller withObject:0];
[controller release];
}
sometimes it is just easier to create an objc class which may contain a simplified (generic) interface for this purpose (i.e. reusable beyond this object), or to use more traditional threading routines (pthreads). if this is the only case in the project, then it should be fine. otherwise, you end up with many utility classes/symbols and much more to maintain. illustration:
#interface MONAudioControllerWrapper : NSObject
{
AudioController audioController_;
std::string asset_;
}
+ (MONAudioControllerWrapper *)newMONAudioControllerWrapperWithAsset:(const std::string&)asset;
- (void)playStream;
#end
#implementation MONAudioControllerWrapper
+ (MONAudioControllerWrapper *)newMONAudioControllerWrapperWithAsset:(const std::string&)asset
{
/* ... */
}
- (void)secondaryWorker
{
NSAutoreleasePool * pool([NSAutoreleasePool new]);
audioController_->RotateThread(asset_);
[pool release];
}
- (void)playStream
{
[NSThread detachNewThreadSelector:#selector(secondaryWorker) toTarget:self withObject:0];
}
#end
As others have said, you can't use detachThreadWithSelector: passing a C++ object as a target or using a C++ method as the selector.
You have two strategies:
wrap the object and selector with an OBjective-C object and selector e.g.
myAudioControllerWrapper = [[OCAudioControllerWrapper alloc] initWithRealController: this];
// need some code to release once thread is complete
[NSThread detachNewThreadSelector: #selector(wrapperSelector:) target: myAudioControllerWrapper withObject: soundKeyAsNSObject];
and your wrapper selector looks like:
-(void) wrapperSelector: (id) key
{
cppController->rotateThread([key cppObject]);
}
Use some other thread mechanism more in keeping with the C++ paradigm. Grand Central Dispatch might be the one if your platform supports it.
I have a C++ class 'Expression' with a method I'd like to use in my Objective-C class 'GraphVC'.
class Expression {
double evaluate(double);
}
And my Objective-C class:
#implementation GraphVC : UIViewController {
- (void)plot:(double(*)(double))f;
#end
I thought that it would be easiest to pass around function pointers that take a double and return a double, as opposed to C++ objects, but I haven't had much success using functional.h. What's the best way to use my C++ method from Objective-C?
EDIT: Thanks for your quick responses. Allow me to elaborate a bit... I have a backend written in C++ where I manipulate objects of type Expression. There's subclasses for rational, polynomial, monomial, etc. My initial idea was to use mem_fun from , but I wasn't able to get code compiling this way. I also had trouble using bind1st to bind the this pointer.
Writing an Objective-C wrapper is a possibility, but I'd rather use the already existing evaluate() function, and I don't want to break the clean separation between the backend and the iPhone GUI classes.
I can't have a global expression or use a static method (I need to plot arbitrary Expression instances.
I should have more explicitly stated that I need to pass a C++ member function (not a static function or existing C function) to an Objective-C object. Has anyone had luck using C++'s <functional> to turn member functions into pointers I can use in an Objective-C object, or should I use an Objective-C wrapper?
If you want to make a pointer to a method in C++, you need to include the class name, like this:
class Foo
{
public:
double bar(double d)
{
return d;
}
};
void call_using_obj_and_method(Foo *f, double (Foo::*m)(double d))
{
(f->*m)(3.0);
}
int main()
{
Foo f;
call_using_obj_and_method(&f, &Foo::bar);
return 0;
}
Note that you need an instance of the class as well. In my example this is another parameter, though you could let it be a global variable, or a singleton instance of class Foo.
Though, like jkp said, you can also solve the problem by making the method static or turning it into a regular function.
EDIT: I'm not sure if I understand your question correctly. I don't think you need to use functional. Here is how my example would look in Objective-C++:
#include <Cocoa/Cocoa.h>
class Foo
{
public:
double bar(double d)
{
return d;
}
};
typedef double (Foo::*fooMethodPtr)(double d);
#interface Baz : NSObject
{
}
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m;
#end
#implementation Baz
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m
{
(f->*m)(3.0);
}
#end
int main()
{
Foo f;
Baz *b = [[Baz alloc] init];
[b callFooObj:&f method:&Foo::bar];
return 0;
}
I would suggest wrapping the C++ class in an Objective-C class, and then also providing a
- (void) plotWithObject:(id)obj
{
double result = [obj evaluate: 1.5];
// ... etc ...
}
in addition to the plot: method.
I think the problem here is that you are trying to pass a member function of your Expression class to the Objective-C class. This will not work because it's expecting a this pointer as the first argument to that function (therefore the signature is not the same as the one expected by the plot: method.
If you make the C++ method a static, you can do this, but then you don't buy yourself a lot over using a standard C function.
IE, if the Expression class looked like this:
class Expression {
static double evaluate(double);
}
You should be able to call it like this:
[self plot:myExpression.evaluate(&Express::evalulate)];
As I say though, there isn't a huge amount of value in this because you may as well be using a standard C function (unless you can do something in the C++ class that is more useful to you).
I did once look at trying to bridge boost::bind() results with objective-c methods but didn't get very far. I'm sure if you dig deep enough in the C++ runtime you could do it though.
If your C++ member function returns a double, can't your code just look like this?
- (void)plot:(double)f;
...
[self plot:myExpression.evaluate(aDouble)];
Or something similar. I've not used much mixing of Obj-C and C++, but this is how I would approach it. You also might have to have a .mm extension on your Objective-C++ file if you're mixing them like that.
Why wouldn't you pass the instantiated c++ class around inside an NSValue and then call the c++ method directly?
- (NSValue*)getExpression
{
Expression* e = new Expression();
return [[NSValue alloc] initWithPointer:e];
}
- (void)callExpression(NSValue*)expression
{
Expression* e = [expression pointerValue];
e->evaluate();
}