How can OpenCV element pointer exist in Obj-C Class? - c++

I am a new settle in Obj-C.
I want to wrap a OpenCV class in Obj-C.
I have a C++ class now, it is like:
class cxx {
private:
IplImage* image;
public:
cxx ();
void modify ();
};
Now I am rewriting in Obj-C, I get confused in the memory type of the pointers.
I put it in a class:
class obj_c:NSObjec {
IplImage* image;
}
- (id) init;
- (void) modify;
But I don't how to deal with the right property of the pointer IplImage*.
If I don't set any property, I can't even access the pointer in the function.

#interface objc_c : NSObject {
IplImage * image;
}
- (id)init;
- (void)modify;
#end
That's how you make a class in objective-c. And in the body of the functions, init and modify, yes, you will be able to access the pointer. You don't have to declare properties unless you want to access an ivar from outside of the class (typically).

Related

Is there a way to pass function from objective-c++ to standard c++?

I want to pass objective-c++ function pointer to standard c++ so that I can call objective-c method on C++.
Here is what I want to achieve:
//C++ side
class CppSide
{
public:
void(*TestFunction)();
};
//objective-c++ side
#interface InteropController : GLKViewController{
}
-(void) PickFile; //I want to pass PickFile address to TestFunction
#end
Following is what I did, but doesn't work
InteropController* controller = [[InteropController alloc] init];
CppSide* cppSide = new CppSide();
cppSide->TestFunction = [controller methodForSelector:#selector(PickFile:)];
cppSide->TestFunction(); //EXC_BADccess(code=1, address=0x2d)
How should I do?
The lazy, easy way is to pass an std::function that calls the objC code (eg, with a lambda).
However, what you have there is a raw C function pointer. You will need to write a C function (or use a non-capturing lambda):
cppSide->TestFunction = [](){ ... ObjC Code here ...};
However, you have no way of referring to the parent scope there - only to the global scope.
If you can change that instead to use an std::function, you will have much more flexibility:
cppSide->TestFunction = [=](){[controller PickFile: ... ];};
If you can't, for some reason, change that function pointer type, consider changing it so that it at the very least expects a data pointer:
class CppSide
{
public:
void(*TestFunction)(void *data);
};
And then you can do:
cppSide->TestFunction = [](void *data) {
InteropController* controller = static_cast<InteropController*>(data);
[controller PickFile: ... ];
}
The caller that invokes the function pointer then needs to explicitly pass a controller.

Calling objective C method from c++ class method

Is it possible to call an objective C method from a C++ class method? I am aware this has been answered to an extent but none of the accepted answers appear to be working for me as I get 'use of undeclared identifier' when trying to use the objective C instance variable (a pointer to self) to call the method.
#interface RTSPHandler : NSObject {
id thisObject;
}
implimentation:
-(int)startRTSP:(NSString *)url {
thisObject = self;
// start rtsp code
}
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned ) {
[thisObject receivedRTSPFrame:fReceiveBuffer];
}
-(void)receivedRTSPFrame:(NSMutableData* )data {
// decode frame..
}
error: use of undeclared identifier 'thisObject'
Try to declare thisObject as a static variable like below
static id thisObject;
#implementation RTSPHandler
//...
#end
UPDATE
Ok. Now I see my answer is hilarious. Let's get through the task and make the solution more appropriate.
There will be two separate classes with separated interface and implementation parts. Say the objective-c class named OCObjectiveClass (Objective-c class) and DummySink (C++ class). Each DummySink instance must have an object of OCObjectiveClass as a c++ class member.
This is interface part of OCObjectiveClass (with a ".h"-extension):
#interface OCObjectiveClass : NSObject
//...
- (void)receivedRTSPFrame:(void *)frame; // I don't know what is the frame's type and left it with a simple pointer
//...
#end
This is the interface part of DummySink (with a ".h"-extension too):
#import "OCObjectiveClass.h" // include objective-c class headers
class DummySink
{
OCObjectiveClass *delegate; // reference to some instance
//...
void AfterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,struct timeval presentationTime, unsigned);
//...
}
AfterGettingFrame function realization must be in DummySink class implementation part (not ".cpp" extension, it must be ".mm" to work with objective-c classes and methods).
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned ) {
[delegate receivedRTSPFrame:fReceiveBuffer];
}
Don't forget to set the delegate value.
- (void)someMethod
{
OCObjectiveClass *thisObject;
// initialize this object
DummySink sink;
sink.delegate=thisObject;
sink.DoWork();
}

How to call C++ method from Objective-C Cocoa Interface using Objective-C++

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.

How could NSArray take ownership of a c++ object

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.

was not declared in this scope

I am new in C++ and working on a project with QT. I created a header file called imageconvert.h which is as follow:
class ImageConvert
{
private:
IplImage *imgHeader;
uchar* newdata;
public:
ImageConvert();
~ImageConvert();
IplImage* QImage2IplImage(QImage *qimg);
QImage* IplImage2QImage(IplImage *iplImg);
};
also I defined those public methods in imageconvert.cpp file.
Now, I want to call QImage2IplImage and IplImage2QImage from other cpp file. So i include imageconvert.h in that CPP file and called those two functions.
it gives the the following errors:
error: 'QImage2IplImage' was not declared in this scope
error: 'IplImage2QImage' was not declared in this scope
Any help would be greatly appreciated.
The functions you've defined are member functions of the ImageConvert class. You need an instance of that class to be able to call them.
Something like:
ImageConvert ic;
ic.QImage2IplImage(your_QImage_object);
If you don't need state to do the conversion, you should make those helper functions static. Then you can call them with:
ImageConvert::QImage2IplImage(your_QImage_object);
without first creating an instance of ImageConvert. But please note that you will not be able to use imgHeader or newData in those static functions - they are member variables, only usable within an instance of that class.
You could also remove these functions from your class and put them in a namespace.
Your question...
How exactly do you call those functions? Given your ImageConverter class, this is how you should be doing it:
// First create a new converter
ImageConverter conv;
IplImage* ipl = conv.QImage2IplImage(qimg);
qimg = conv.IplImage2QImage(ipl);
... And some advice on using classes
Do you by any chance come from a Java or C# background? If so, you should know that in C++ you can also have free functions (that don't belong to any class). You should only use classes when you need to abstract a certain (real world) concept, and not simply as a way to group functions:
// image_converter.h
IplImage* QImage2IplImage(const QImage* qimg);
QImage* IplImage2QImage(const IplImage* iplImg);
// someother.cpp
IplImage* ipl = QImage2IplImage(qimg);
qimg = IplImage2QImage(ipl);
Notice I added const to the function parameters — it's a good thing to be const correct. Additionaly, you can group your functions in a namespace:
// image_converter.h
namespace converter
{
IplImage* QImage2IplImage(const QImage* qimg);
QImage* IplImage2QImage(const IplImage* iplImg);
}
// someother.cpp
IplImage* ipl = converter::QImage2IplImage(qimg);
qimg = converter::IplImage2QImage(ipl);