example Objective-C project calling Objective-C++ code - objective-c

Anyone know of an example project of a Objective-C project calling Objective-C++ code.
I've read all the stackoverflow q's about getting one to call the other but no luck.
Would help if I had a code sample that worked.
The Obj-C++ I have is a lib .a and some c++ headers. Thats all.

Here's example project I made, it's actually easy to undestand, you can just rename your classes from .m to .mm or in project settings set "Compile sources as" to Objective-C++. I have had some trouble with C++ headers which didn't have C++ implementation as well - changing settings to compile everything as Objective-C++ helped.
Here's the code https://github.com/libec/StackOverflow/tree/master/03-Obj-C%2B%2B

Here's a contrived example. Without more information about what you're trying to do, or the errors you're receiving, it will be impossible to guide you much further. Remember that any code that calls C++/Objective-C++ code or imports a header that includes C++-isms must be compiled as Objective-C++ (use the .mm extension and Xcode will automatically do the right thing).
/*Objcpp.h
**********/
#interface MyClass : NSObject
{}
- (void)myMethod;
#end
/*Objcpp.mm
***********/
#import "Objcpp.h"
#implementation MyClass
- (void)myMethod {
//some c++ and/or objective-c calls
}
#end
/*myobjc.h
***********/
#interface MyObjCClass : NSObject
{}
- (void)someMethod;
#end
/*myobjc.mm
***********/
#import "myObjCClass.h"
#import "Objcpp.h"
#implementation MyObjCClass
- (void)someMethod {
MyClass *o = [[MyClass alloc] init];
[o myMethod];
}
#end

Related

Use Objective-C without NSObject?

I am testing some simple Objective-C code on Windows (cygwin, gcc). This code already works in Xcode on Mac. I would like to convert my objects to not subclass NSObject (or anything else, lol). Is this possible, and how?
What I have so far:
// MyObject.h
#interface MyObject
- (void)myMethod:(int) param;
#end
and
// MyObject.m
#include "MyObject.h"
#interface MyObject()
{ // this line is a syntax error, why?
int _field;
}
#end
#implementation MyObject
- (id)init {
// what goes in here?
return self;
}
- (void)myMethod:(int) param {
_field = param;
}
#end
What happens when I try compiling it:
gcc -o test MyObject.m -lobjc
MyObject.m:4:1: error: expected identifier or ‘(’ before ‘{’ token
MyObject.m: In function ‘-[MyObject myMethod:]’:
MyObject.m:17:3: error: ‘_field’ undeclared (first use in this function)
EDIT My compiler is cygwin's gcc, also has cygwin gcc-objc package:
gcc --version
gcc (GCC) 4.7.3
I have tried looking for this online and in a couple of Objective-C tutorials, but every example of a class I have found inherits from NSObject. Is it really impossible to write Objective-C without Cocoa or some kind of Cocoa replacement that provides NSObject?
(Yes, I know about GNUstep. I would really rather avoid that if possible...)
EDIT This works:
// MyObject.h
#interface MyObject
#end
// MyObject.m
#include "MyObject.h"
#implementation MyObject
#end
Not very useful though...
It's possible to make classes without a base class. There are a couple of things going on. First, your compiler doesn't seem to like the "()" class extension syntax. Other compilers would be OK with it. If you remove those "()" on line four of MyObject.m then your compiler will complain that you've got two duplicate interfaces for the MyObject class. For the purpose of your test you should move that _field variable into the declaration of MyObject in the header file, like:
#interface MyObject {
int _field;
}
-(void)myMethod:(int)param;
#end
Then you can completely remove that extra #interface in the .m file. That should get you started at least.
It's possible, but note that NSObject implements the memory allocation API in objective-c, and if you don't implement NSObject's +alloc and -dealloc or equivalent on a root class, you'll still need to implement the same functionality for every class.

How to call Objective-C++ (.mm) from Objective-C (.m)

Is there a say to do this without changing every .m file to .mm?
OK. I am trying to implement the answer but having trouble. Take a look at my Objective C++ .h and .mm below
Objective-C++ - IDCaptureTemplateCommand.h:
#include "Template.h"
#interface IDCaptureTemplateCommand : NSObject
#property (nonatomic, strong) IDCaptureTemplateCommand *IDCaptureTemplateCommand;
#end
Objective-C++ - IDCaptureTemplateCommand.mm:
#include "IDCaptureTemplateCommand.h"
#implementation IDCaptureTemplateCommand
- (id)init
{
self = [super init];
if (self) {
self.captureTemplateCommand = [[IDCaptureTemplateCommand alloc] init];
}
return self;
}
#end
Objective-C - IDCameraViewController.h
#import <UIKit/UIKit.h>
#import "IDCaptureTemplateCommand.h"
#interface IDCameraViewController : UIViewController <UINavigationControllerDelegate>
#property (nonatomic) IDCaptureTemplateCommand *captureCommand; //ERROR - Unknown type name 'IDCaptureTemplateCommand'
#end
You can do so in the same way as you can use C++ from C or whatever. You need to be able to declare the interface using pure Objective-C and then the implementation can be written using Objective-C++.
If your header file uses C++, e.g. your class has an std::string instance variable, then to make the functionality accessible from Objective-C you have to write a wrapper or otherwise hide the C++ at the interface, so that your Objective-C files don't need to see any of the C++ declarations.

Using Methods Without Declaring them in the header

Recently I used an opaque pointer type in my code. I did this because I wanted to use c++ code in my obj c project without having to change every single file to .mm.
The way I use the c++ code is that I have a opaque pointer to my c++ code as a member of a .mm file. All the c++ is hidden in the implementation file.
In this class that contains my c++ I have a need to import an existing class "MyClass". I can import it fine in the implementation class but if I try to import it in the header I get c++ errors saying " ISO C++ forbids declaration of 'CARingBufferCPPWrapper' with no type".
I "can" just write the method in the .mm file and omit it from the header but I get a warning say that my .mm file may not respond to the method.
A lot of this is quite new to be so my terminology may be a little off. Let me know if I can clarify my question in any way.
TLDR: How can Class X Safely call a method in Class Y without the method being declared in Class Y header?
//My Header
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#define kBufferLength 5120
//#define "Myclass.h"
typedef struct ringbufferobj * RingBufferOBJ;
RingBufferOBJ newRingBufferOBJ();
#interface CARingBufferCPPWrapper : NSObject {
RingBufferOBJ ringbuffer;
NSThread *producerthread;
int duration;
}
#property (nonatomic, retain) NSThread *producerthread;
#property(nonatomic)int duration;
//-(void)myclassfunction(MyClass *)classref
#end
//My Implementation .mm
#import "CARingBufferCPPWrapper.h"
#import "CARingBuffer.h"
#import <AudioToolbox/AudioToolbox.h>
#import "MyClass.h"
struct ringbufferobj
{
CARingBuffer *ringbuffer;
AudioBufferList *inputbuffer;
Float64 firstInputSampleTime;
Float64 firstOutputSampleTime;
Float64 inToOutSampleTimeOffset;
BOOL producerthreadisrunning;
};
RingBufferOBJ newRingBufferOBJ(){
RingBufferOBJ ringbuffer=(RingBufferOBJ)malloc(sizeof(struct ringbufferobj));
return ringbuffer;
}
#implementation CARingBufferCPPWrapper
#synthesize producerthread;
#synthesize duration;
-(void)myclassfunction(MyClass *)classref
{
}
#end
I'm not quite sure what your question is as I couldn't find anything that actually asks anything. (I even Cmd+F'd for "?"). I'm assuming however, that you're asking what you can do to get rid of that warning?
-If a method is declared above the method it is called it, there should be no warning. ( methods are compiled in order). To get rid of such a warning, you'd have to forward declare the method signature. (This is conventionally in the header, but I don't think there's anything stopping you just doing it at the top of your .m)
-(void) methodA {
..do something
[self methodB]; //Warning here because the compiler has not yet seen methodB
}
-(void) method B {
..[self methodA]; //No warning, compiler knows what methodA is at this point.
}

Cocoa: Build Warning that s Forward Declared Class's and #interface May not Exist

I am trying to build the Clustering Plug in my project under Leopard. I have following two questions.
In the project an interface class is defined as
#interface ClusteringController : NSWindowController
{
.......
.....
....
}
#end.
And this class is used in implementation class using forward declaration:
#class ClusteringController;
then in one function it is used as:
- (long) filterImage:(NSString*) menuName
{
ClusteringController *cluster = [[ClusteringController alloc] init];
[cluster showWindow:self];
return 0;
}
When I build this project it produces the warning:
warning: receiver 'ClusteringController' is a forward class and corresponding #interface may not exist
Also there is one more warning produced:
warning: no '-updateProxyWhenReconnect' method found
This warning is coming for the following line of code:
if(delegate) [delegate updateProxyWhenReconnect];
Can anybody help me to overcome these warnings?
A forward declaration is used when the header file will be imported after the interface. It looks to me that you've used the #class directive after the interface for the class itself.
The normal use of a forward class declaration looks like this:
#import "SomeSuperClass.h"
#class Forwardclass;
#interface SomeClass : SomeSuperClass
{
Forwardclass anIvar;
}
#property Forwardclass anIvar;
#end
#import "SomeClass.h"
#import "ForwardClass.h"
#implementation SomeClass
#synthesize anIvar;
-(void) setAnIvar:(ForwardClass *) aForwardClass;
#end
The #class directive is never used in an implementation (.m) file.
That's not what #class is for.
You use #class in the header file for another class, to tell the compiler that the class you're declaring does exist. Without it, the compiler would not know that that's a class name, and when you declare a variable as holding a pointer to an instance of that class, the compiler would think that you're just making up words. Using #class is called forward-declaring the class.
Your situation is different. You're in the implementation file for that class.
What the compiler needs from you now is the class's #interface. The warning is telling you that the compiler needs an #interface, but you haven't given it one (so, as far it knows, the #interface “may not exist”).
Normally, you would have written the #interface in a header file; how now to get it into the implementation file?
That's where the preprocessor comes in, with its #import directive. At the top of the implementation file (ClusteringController.m), import the header file:
#import "ClusteringController.h"
The preprocessor will replace this with the contents of that file, then hand the preprocessed code to the compiler, which will see the #interface there.

how to return C++ pointer in objective-C++

I have the following objective-C++ header with the simple method to return this pointer.
#interface MyObj
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
I have created the simple method
#implementation MyObj
-(MyCPPObj *) getObj
{
return cpp;
}
Everything seems to work until I actually try to use the object in another file
newObj = [createdMyObj getObj];
It complains: error: cannot convert 'objc_object*' to 'MyCPPObje *' in initialization.
It seems that the method is return an objective-c object, but I specifically requested a C++ pointer.
MyCPPObj is an honest C++ class:
class MyCPPObj
{
public:
int x;
}
How can I fix that?
On my 10.6.3 machine, the following combination worked without any problem: aho.h
#import <Foundation/Foundation.h>
class MyCPPObj{
};
#interface MyObj:NSObject
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
#end
and aho.mm
#import <Foundation/Foundation.h>
#import "aho.h"
void foo(){
MyObj*objcObj=[[MyObj alloc] init];
MyCPPObj*cppObj=[objcObj getObj];
}
Two pitfalls you might have fallen into:
Unlike C++, a class in Objective-C which doesn't inherit from NSObject won't work. (Well, you can make it work, but you don't want that usually.) Note the line #interface MyObj:NSObject.
To use NSObject, do #import <Foundation/Foundation.h>
Don't forget to use the extension .mm for Objective-C++ files.
Most likely you have forgotten to #import the header file with the #interface into the .mm file where you use getObj.
The error states what happens, and JeremyP is right on the money. When you forget to include a header file with the prototypes of the selectors, the compiler assumes the selector returns an object of type id. Well id is a typedef to objc_object*, which is incompatible with your C++ class. To fix the error, you simply need to include your header file in the file where you called getObj.