I have a pure C++ class that needs to retrieve an int value from some Objective-C instance method.
I understand that C++ cannot call Objective-C methods directly.
I have an Objective-C++ class that allows me to work with Objective-C and also to pass data to my pure C++ class.
However, I have not figured out a way to allow the pure C++ class to request the int value be computed and retrieved. In other words, the pure C++ needs to be able to retrieve that value whenever it needs to (via a function pointer, or whatever).
Anyone know how this is accomplished?
C++ can definitely call Objective-C code. Store the code that communicates in a .mm file instead of .cpp, and Xcode will do the rest for you.
.mm files store Objective-C++ code, which is why it works.
[Edit]
You probably have some business logic in C++, and want to combine that with your UI in Objective-C, right? Your business logic is probably shared across multiple platforms, which is why you can't just compile all your code as Objective-C++.
That's why you can basically "wrap" your Objective-C code in an Objective-C++ wrapper.
// myUI.h (C++ header)
class myUI {
void doSomething1();
int doSomething2();
}
// main.cpp (C++ code)
int main() {
myUI ui;
printf("%d\n", ui.doSomething2());
ui.doSomething1();
return 0;
}
// myUI.mm (Objective-C++ code)
int myUI::doSomething2() {
return [[MyController sharedController] doSomething2];
}
// myUI.cpp (C++ code)
void myUI::doSomething1() {
printf("Hi!\n");
}
Related
I have following C++ abstract class i have to implement this abstract class in objective C. This interface expects std::shared_ptr and std::vector. Can i implement this class in objectve-C. Or is there any alternative to implement this class in objective-C.
Note: Reason behind implementing this class in objective-C is because i am writing a wrapper for iOS Metal for the defined interface. And iOS metal did not have C++ API it has only objective API.
class GPUDevice{
public:
virtual ~GPUDevice() {
}
virtual GPU_TYPE getType() = 0;
std::vector<GPU_OPERATIONS> supportedGPUOperations{GPU_OPERATIONS::RENDERING,GPU_OPERATIONS::COMPUTE};
virtual std::shared_ptr<GPUQueue> createQueueForOperation(GPU_OPERATIONS gpuOperations) = 0;
virtual std::shared_ptr<GPURenderPass> createRenderPass(GPUTextureFormats formats) = 0;
virtual std::shared_ptr<GPUPipeLine> createGPUPipeline(const std::string& fragmentShader, const std::string& vertextShader,const std::shared_ptr<GPURenderPass>& renderpass,const std::vector<GPUBinding>& bindings) = 0; };
Just rename your file from .m to .mm it tells the compiler you are using objective C++. You can use C++ code after that.
To use C++, as other have cited, you'll need to define the file as Objective-C++. One does not need to rename files. Yes, renaming the file to use .mm will automatically do this. However, there is another way which is helpful when you have pre-existing files (ie. files already named with .cpp or some other C++ extension).
You can change the type to Objective-C++ Source in the File Inspector (Available in the menu View:Inspectors:Show File Inspector or using the shortcut Opt+Cmd+1).
NOTE: If the file is already a .m then I do recommend changing the extension to .mm.
You'll see the following on the right. Just change Type.
I don't want to use NSNotification because it is so messing up internally. Is it a way to pass a callback function from C++ to Objective-C++, and let Objective-C call it?
The problem is that I don't know how to pass a function written in C++ to Objective-C++, and how could I use that callback in Objective-C++? Is it a pointer?
I know I can mix them up but my class has to be a C++ class because it inherits some C++ classes.
You're not 100% specific as to the exact use case you're trying to cover here, but I'm going to set out a scenario where this kind of situation occurs, and then show you how to solve it. I hope that will cover your problem too.
So I'm going to assume you have an Objective-C class MyClass with its interface declared in MyClass.h:
#interface MyClass : NSObject
- (void)someMethod;
- (void)otherMethodWhichShouldTakeACallback:?????;
#end
You now have a C++ class MyCPPClass, declared in MyCPPClass.hpp on which you want to pass memberFunction as the callback argument to the otherMethod on MyClass:
class MyCPPClass : public MyBase
{
void memberFunction();
};
First, we need to figure out the method signature on MyClass. The modern way for callbacks in Objective-C is with Blocks. Blocks work pretty well with Objective-C++, so let's go with that and modify MyClass.h with the following line:
- (void)otherMethodWithBlock:(void(^)(void))callbackBlock;
The calling code will need to reside in an Objective-C++ compilation unit (caller.mm):
void callOtherMemberWithCPP(MyCPPClass* cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
Note that this does not deal with object lifetimes. If you're managing lifetimes on the C++ side with std::shared_ptr, you can use that in your Objective-C++ code too, in which case we might end up with something like:
void callOtherMemberWithCPP(std::shared_ptr<MyCPPClass> cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
In this case, the C++ object will only have its reference count decremented when the Objective-C class is done with the block.
For completeness, the other way to do this would be to use C function pointer syntax. In this case, you would need to declare the Objective-C method along these lines:
- (void)otherMethodWithCallback:(void(*)(void*))callback object:(void*)opaqueCallbackArgument;
And the C++ class's method call would need to be wrapped in a free function or static member function:
void memberFunctionCallback(void* opaque_object)
{
MyCPPClass* object = static_cast<MyCPPClass*>(opaque_object);
object->memberFunction
}
…and then call the Objective-C method like this:
[objc_obj otherMethodWithCallback:memberFunctionCallback object:cpp_obj];
Making this version work nicely with automatic lifetime mechanisms such as shared_ptr is a lot more tricky though.
In my previous revision game engine I deported major functions for the game editor for C#. Now, I'm beginning to revise the game engine with a static library. There's a already dynamic library created in C++ to use DLLEXPORT for C#. Just now I want to test out the newer functions and created a DLL file from C++. Because the DLL contains classes I was wondering how would I be able to use DLL Export. Would I do this:
[DLLEXPORT("GameEngine.dll", EntryPoint="SomeClass", Conventional=_stdcall)]
static extern void functionFromClass();
I have a feeling it's probably DLLImport and not DLLExport. I was wondering how would I go about this? Another way I was thinking was because I already have the DLL in C++ prepared already to go the C# Class Library. I could just keep the new engine as a lib, and link the lib with the old DLL C++ file.
Wouldn't the EntryPoint be able to point to the class the function is in?
You can't actually export C++ classes directly like this.
static extern void functionFromClass();
The problem with C++ is that it doesn't have a universally defined ABI (Application binary interface). So In order to make other languages understand your C++ library ABI you need to wrap it with C functions (almost every other language understands C).
The problem with C is that it doesn't understand classes. On the other hand, C++ Objects need to pass this pointer as a parameter to their member functions. So in order to wrap your C++ classes with C interface. You need to handle passing this parameter explicitly and also define functions similar to the constructor and destructor.
You need to do sth like this:
//Header File Foo.h
struct Foo; // Forward Declaration Only
Foo* createFoo( /* parameters */ );
void destroyFoo( Foo* obj );
int Func( Foo* obj, int i ); // obj should take this pointer
float Func2( Foo* obj, float i, float j );
Implement it like this
#include "Foo.h"
extern "C"
{
Foo* createFoo( const char * s )
{
return reinterpret_cast<Foo*>( new Foo( s ) );
}
void destroyFoo( Foo* obj )
{
delete reinterpret_cast<Foo*>(obj );
}
int Func( Foo* obj, int i )
{
return reinterpret_cast<Foo*>(obj)->Func(i);
}
}
Finally you can wrap your exported C function in a C# class so things get back to the traditional object oriented way.
Notice that I didn't even mention Inheritance or polymorphism.
You cannot import native C++ classes directly to C#. They need to be wrapped one way or another. You can wrap them with C style non-member functions. You'll need to export functions that create and destroy the instances. All in all it's pretty horrid process.
The smart way to do this is to wrap compile the native C++ code into a mixed-mode C++/CLI assembly. You can then expose the functionality as a managed ref class. The interop then becomes trivial and you don't need to run the gauntlet of writing p/invoke declarations by hand.
I Would suggest taking a look at COM Objects and using COM Interop to communicate between Cpp and C# program.
I have a growl action I need to call from Objective C++
- (NSDictionary *) registrationDictionaryForGrowl {
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObject:#"Alert"], GROWL_NOTIFICATIONS_ALL,
[NSArray arrayWithObject:#"Alert"], GROWL_NOTIFICATIONS_DEFAULT
, nil];
}
is the action in Objective C, but I need to put it in a .mm file (Objective C++) and I'm having a hard time trying to convert it properly because I need to put it inside a (C++) function inside a (C++) class.
Any idea how I could transfer this over to Objective C++?
From what I gather you want to provide a C++ object to Growl, which expects and Objective-C object. You can't do this.
Objective-C is a set of language extensions welded onto C. Objective-C++ is the result of welding exactly the same extensions onto C++. So in Objective-C++ you have both Objective-C style objects and C++ objects, and they are completely different things. One cannot be used when the other is expected. They have different ABIs, different schemes for resolving a method call/message send, different lifetime management, etc.
The purpose of Objective-C++ is not to make Objective-C objects and C++ objects compatible, but simply to make Objective-C code usable from C++ and C++ code usable from Objective-C++.
So what you could do is create your C++ class that you want to use as a delegate, and then create an Objective-C++ class that wraps your C++ class and has methods that simply forward to an instance of your C++ class.
class Foo {
int bar(int i) { return i+1; }
};
#interface ObjCFoo : NSObject
{
Foo foo;
}
- (int) bar:(int) i;
#end
#implementation ObjFoo
- (int) bar:(int) i;
{
return foo.bar(i);
}
#end
In Objective-C++ there are C++ classes and Objective-C classes. There are no Objective-C++ classes. The GrowlApplicationBridgeDelegate which implements registrationDictionaryForGrowl has to be an Objective-C object. You can define it exactly same in an .mm file as you would in an .m file. The only difference is that in your .mm file the Objective-C classes you define can call and use C++ classes and syntax.
I do not know what do you call Objective-C++, but the code above, provided it is in an Objective-C #implementation section, will compile fine with or without Objective-C++ enabled (.m or .mm extension).
By the way, if you are using Xcode 4.4 or above, the following will do as well:
- (NSDictionary*) registrationDictionaryForGrowl {
return #{
GROWL_NOTIFICATIONS_ALL : #[ #"Alert" ],
GROWL_NOTIFICATIONS_DEFAULT : #[ #"Alert" ] };
}
I am having some trouble calling an objective-c class method from a C++ file. Example:
In my .h:
#interface MyClass : NSObject {
}
+ (void)myMethod:(NSString *)str;
In my .m:
+ (void) myMethod:(NSString *)str { ... }
In my .cpp:
??
How can you call myMethod since there is no class instance? Its essentially a static?
Thanks
Objects in C++ are incompatible with objects in Objective-C. You cannot simply call an Objective-C method from C++.
There are some solutions, however:
Use Objective-C++. Rename your .cpp to .mm, then you can use Objective-C syntax in your C++ code: [FlurryAnalytics myMethod: #"foo"];
Use direct calls to the Objective-C runtime system. I won't tell you how to, because I really think you shouldn't, and in fact that you don't want to.
Write a plain-C interface. That is, in some .m file, define void myFunction(const char *str) { ... } and call that from C++. You can find an example of this here.
You're going to need a .mm to call an Objective-C method, rather than a .cpp. Beyond that your comment that 'it's essentially static' is accurate in the sense that you would call it with similar logic to the way you would call static class functions in C++:
[MyClass myMethod:#"Some String"];
Though the method isn't static in the C++ sense for a bunch of reasons that don't affect this answer — it isn't resolved at compile time and it does operate within a class (the MyClass metaclass).