How to pass a callback function from C++ to Objective-C - c++

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.

Related

How to set a class function to behave as another class function

I have two classes, ClassWorking and TemplateClass, they are not related in any way.
Is there a way to say, I want the function TemplateGenerate() from my TemplateClass now to behave like the function generate() from my class ClassWorking.
Like a (this function does not exist) SetFunctionBehavior(&templateClassRef->templateGenerate, &classWorkingRef->generate)
I know I can use function pointer to make TemplateClass receive a pointer and call it in the class, but that not what I want.
It's more something like a LD_Preload, to replace the inner of function without having to re-write it and without inherit from a class who has it.
to be a little more explicit let's see it more like a node construction for class
TemplateClass can have multiple functions but not with the same behaviour
- TemplateClass
- TemplateGenerate() {will do this}
- TemplateGenerate() {will do that}
- TemplateGenerate() {will do like that}
and when I declare my class pointer templateClassRef->TemplateGenerate = TemplateGenerate() {will do that}
but not with a lambda :)
The point is to have something really generic without having to re-create a class for each need, for example I could have a class:
TemplateGenerate
- function A {A1 Behavior} Functiun B {B1 Behavoir} Functiun C {C1 Behavior}
{A2 Behavior} {B2 Behavoir} {C2 Behavior}
{A3 Behavior} {B3 Behavoir} {C3 Behavior}
And when I declare my function I say I take A1,B2,C3 or A1,B1,C2
The method ClassWorking::generate is a function that takes a ClassWorking and does stuff.
A function that has the same behaviour also takes a ClassWorking. That is part of what the function does.
As TemplateClass is unrelated to ClassWorking, a method TemplateClass::templateGenerate that "behaves alike" ClassWorking::generate cannot succeed; you don't have a ClassWorking, so one of the prequisites of ClassWorking::generate isn't being fullfilled.
Now, it might be the case that the implementation of ClassWorking::generate doesn't actually need an instance of ClassWorking. It might need something else.
But for the compiler to know this, you have to change the method from being a method of ClassWorking to being something else. For example, you could write a free function generate that takes an argument what you actually need, and have ClassWorking::generate call that free function.
Then calling the free function generate from a stub method TemplateClass::templateGenerate becomes trivial.
C++ does not support "do what I mean" or "read my mind". You actually have to tell the compiler what you want to happen. And types matter in C++, so you cannot wire up a method on one class to another class without also telling C++ how the types relate.
There are languages where types are looser and you actually can grab a method off one class and glue it onto another. These are generally interpreted languages with much heavier runtime object models than C++; members in this language are implemented as property bags of named values, values are actually variants at runtime, etc.
You can implement that kind of object in C++, but it isn't a "native" C++ object, and you'll have to write a pile of glue code (some of which could be hidden by metaprogramming). That is far from a beginner task, and usually a bad idea; if you need the flexibility of scripting languages, just use a scripting language.
One way is to use composition. Define an interface
struct Interface
{
virtual void/*maybe*/ templateGenerate(/*maybe*/) /*const?*/ = 0;
};
Then implement
struct ClassWorkingImpl : Interface, ClassWorking
{
// ToDo - delegate all the constructors
// ToDo - implement templateGenerate using the method in ClassWorking
};
and similarly for TemplateClass.
Then you instantiate ClassWorkingImpl &c. rather than ClassWorking. And you can call the interface method templateGenerate on either.

Getting the address of an Objective-C method

I am new to Objective-C and I need to overcome the following issue.
I am trying to develop a front-end for a C library and I need to somehow get the address of an Objective-C member function and pass it to the library.
For instance: here's what I would do in C++
class MyClass
{
public:
void my function();
void some_other_function()
{ connect_signal(my_function); }
};
Here, I just pass the address of my_function() to connect_signal.
Is that possible in Objective-C? Any other ideas?
My second choice would be to simply write a C function out of the class that would call the Objective-C function.
Thanks in advance
There’s a methodForSelector: method that returns an IMP, a pointer to the implementation of a method for given selector (related question). Is that what you’re after?
And as a more general remark, using a pointer to a method implementation is usually too much magic. Is there a higher-level, more “ordinary” solution to your use case? (I can’t really imagine the details from what you wrote in the question.)
For the record, you can't connect a signal to a nonstatic C++ function. At least not in the *nix meaning of signals. Those need a this pointer for invokation.
Now, about Objective C. Depends on what do you want to do - pass a pointer to an Objective C method to a plain-C API, or implement a signal-like callback mechanism of your own. Other answers concentrate on the former; let's talk the latter.
The natural thing to do is passing around a combination of a selector and an object pointer. Selectors have datatype SEL and are retrieved using the #selector() construct. A selector is a piece of data (really an integer) that uniquely identifies a method within a class hierarchy.
Let's imagine you have a connect_signal function somewhere that wants a callback:
-(void)connect_signal:(SEL)callbackSelector forObject:(NSObject*)callbackObject;
You call it like this (from within the callback object):
[xx connect_signal:#selector(MyMethod:) forObject:self];
Within the function, you save the selector and the object pointer. When you need to invoke the callback, you would issue the following call:
[SavedCallbackObject performSelector:(SavedCallbackSelector) withObject: nil];
The second parameter is for passing parameters to the callback; if you need more than one, see NSInvoke.
My answer is assuming Cocoa. NSObject, e. g. is a Cocoa class. It's a safe bet for ObjC questions these days, considering.
Or you can use good old function pointers. They're still around.
An Objective-C method implementation (IMP) is a C function that takes at least two arguments; the target of the method call (self) and the selector to be invoked (_cmd).
Thus, passing an IMP to your C API won't work.
Your best bet is to pass a C function. Assuming your C API is sensible and has an "arbitrary user context pointer thingy", something like:
void myfunc(void *context) {
[(MyClass *)context callback];
}

Calling an Objective-C class method from C++

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).

Mixing C++ and Objective-C

I am using C++ as the app backbone and Objective-C for the GUI, that's fine.
But when it comes to mixing those code together in Objective-C++ (.mm file), I have got a few question:
1. Can I mix STL containers with Objective-C or Cocos2D objects?
E.g. In Objective-C header, can I do the following?
#include <vector>
#include <boost\shared_ptr.hpp>
#interface MyClass : NSObject {
std::vector<boost::shared_ptr<CCSprite> > m_spriteList;
}
And then in the .mm file, I want to do
CCSprite* newSprite = [/* cocos2d stuff here... */];
m_spriteList.push_back(newSprite);
Is the above code valid? It certainly is in C++, but I am not sure when mixing C++ and Objective-C and Cocos2D.
2. Memory management using C++ smart pointer object in Objective-C?
When I try to use the C++ code in Objective-C, I want to declare a C++ object as a member variable in the Objective-C header file.
Say I have a C++ class declared in the test.h header:
Test{
};
In Objective-C header file, I want to do
#include "test.h"
#incude <boost/scoped_ptr.hpp>
#include <vector>
#interface MyClass : NSObject {
Test* m_testObjectPtr; // (1)
boost::scoped_ptr<Test> m_testOjbSmartPtr; // (2)
}
In the above code, is (2) okay? Can I use smart pointers in Objective-C just like in C++ code? And can I assume the Test class destructor will be called when the MyClass object is destroyed?
Or if (2) is not okay in Objective-C++, is (1) okay? Would I need to manually call
delete m_testObjectPtr in dealloc?
You can use smart pointer only on c++ classes. if you use then on objective-c classes you will either get compile error or crash somewhere.
You can also use containers with pointers of objective-c classes like
std::vector<CCSprite *> spriteList;
just make sure you retain them when you insert them to list and release them when you remove them.
In both cases, you can make a smart pointer of your own that calls retain and release in constructor/destruct/copy like needed and then don't worry about retain release.
Also destructor for member c++ objects will be called automatically when the object is deallocated.
An example of an objective c wrapper would be
template<typename T>
struct shared_objc_object
{
T *Object;
shared_objc_object : Object(nil) { }
shared_objc_object(T *Object) : Object([Object retain]) { }
shared_objc_object(shared_objc_object &other) :
Object([other.Object retain]) { }
~shared_objc_object() { [Object release]; }
shared_objc_object &operator =(shared_objc_object &other)
{
[Object release];
Object = [other.Object retain];
}
}
And you can use
std::vector<shared_objc_object<CCSprite *>> spriteList;
spriteList.push_back(some_sprite);
and don't care about retain/release
There are some issues you'll want to be aware of. C++ classes do not enjoy the same scope based lifetime you might be used to when made into class members of Objective-C++ objects. When alloc/initing, the constructor won't be called, and when releasing, the destructor won't be called, unless you carefully use in place new/delete or hold on to a pointer and explicitly manage it with new/delete.
Also, if the Objective-C++ header needs to be shared with Objective-C files, you cannot use any C++ constructs at all. Both problems can be mitigated by hiding all C++ members using the pimpl pattern.
Can I mix STL containers with Objective-C or Cocos2D objects?
Yes, since Objective-C objects are just pointers to structs, you can store them easily in STL containers and even forward declare the type and pass it into pure C++ code. (Note, the C++ code can't really do much with the pointer without tricky and brittle code, but you can always pass the pointer back into Objective-C code later to get useful work done.)
Memory management using C++ smart pointer object in Objective-C?
You can use smart pointers to manage the lifetime of your Objective-C objects, but you will need to be careful that they do not call delete (the default behavior for most C++ smart pointers). With shared_ptr from C++11 or boost, you can provide a custom deleter; though now you have two reference counting systems. You can instead use boost::intrusive_ptr to skip that extra overhead and use Objective-C's reference counting directly.

How can I use Boost::Python to add a method to an exported class without modifying the base class?

I have a class in C++ that I can't modify. However, that class holds an std::list<> of items that I need to be able to access in a Python extension. Since Boost::Python doesn't seem to have a built-in conversion between an std::list and a Python list, I was hoping to be able to write a method in C++ that could do this conversion for me and later, when I am mapping the C++ classes to Python classes, I could attach this method.
I would prefer if I could just call the method like
baseClassInstance.get_std_list_of_items_as_python_list()
To answer the question in a more general way, you can attach any c++ function that has the right signature to the python export in the class_ declaration.
assume a class foo:
struct foo
{
//class stuff here
}
You can define a free function that takes a reference to foo as the first argument:
int do_things_to_a_foo(foo& self, int a, std::string b, other_type c)
{
//Do things to self
}
And export it just like a member of foo:
class_<foo>("foo")
...
.def("do_things_to_a_foo", &do_things_to_a_foo)
...
;
Boost provides a helper to wrap iterators which is documented here: http://www.boost.org/doc/libs/1_42_0/libs/python/doc/v2/iterator.html
The example hear the end of that page worked for me, you just need to explicitly create the conversion, for example:
class_<std::list<Item> >("ItemList")
.def("__iter__", iterator<std::list<Item> >());
To modify the C++ class without changing it, I am in the habit of creating a thin wrapper that subclasses the real class. This makes a nice place to separate out all the crud that makes my C++ objects feel comfortable from Python.
class Py_BaseClass : public BaseClass {
public:
std::list<Item> & py_get_items();
}