Generic Objective-to-C++ translation strategy - c++

I'd like to expose ObjC notification handlers to my C++ client code.
I'm doing it this way.
I wrapped an ObjC object (call it X) inside a C++ object.
X observes the notification and registers a callback (call it F).
F translates the ObjC structures from the notification into their C++ counterparts, calls a user-registered global C++ callback function (call it FF). The translated C++ structs become the input arguments of FF.
Now the problem is that the arguments' original ObjC structures are complex, containing multiple layers of ObjC objects that need to be translated.
On my side, the wrapper observer F needs to do nothing special, just calling the client's FF.
What is the more proper strategy of my translation at this point?
Should I:
Translate those structures down to the bottom-level of all their members so that I have equivalent C++ structures to use as the arguments, or,
Create a C++ class to wrap these arguments into one object and expose the class interface to user so they can use those C++-wrapped arguments in their C++ implementation, or,
Give up on the wrapping idea and ask user to code in ObjC and register their own observer functions directly?
My targeted users are iOS developers that may or may not be Android developers too.

You can mix c++ and objective-c++ in a .mm implementation file. This means you can give a c++ lambda (or block) to the objective-c++ class that references your c++ owner.
something like this:
implementation.mm:
#interface Shim : NSObject
{
std::function<void>() _notify;
}
#end
#implementation Shim
- void register_cpp(std::function<void>() f)
{
_notify = std::move(f);
}
- (void) my_handler()
{
if(_notify)
_notify();
}
#end
struct cpp_class::impl {
impl()
: _shim([Shim alloc[init]])
{
_shim.register_cpp(std::bind(&impl::callback, this));
}
private:
void callback() {
// do callback here;
}
Shim* _shim;
};
cpp_class::cpp_class()
: _impl(new impl)
{
}
cpp_class::~cpp_class()
{
delete _impl;
}
header.h:
struct cpp_class{
cpp_class();
~cpp_class();
private:
struct impl;
impl* _impl;
};
In reality you'll want to be careful to ensure that objects still exist when doing callbacks (argues for weak_ptr::lock(), enable_shared_from_this, etc.) since objective-c likes to put callbacks onto a thread's run loop (basically a queue) and that means your c++ object can go away before the callback arrives - but this code should give you the right idea.

Related

Is there C++ equivalent of Objective-C Instance and Class Methods?

I am learning C++ with Xcode (cocos2d-x).
A regular c++ void method I think is equivalent to an obj-c -void Instance method.
Is there is a c++ equivalent of the obj-c +void Class method?
Thanks
There is no direct equivalent to class methods in C++; however, in many cases C++ static methods can be used in place of class methods.
For example, this Objective-C code:
#interface MyClass : NSObject
{
int _number;
}
+ (MyClass*)newInstance;
- (void)instanceMethod;
#end
#implementation MyClass
+ (MyClass*)newInstance
{
return [[self alloc] init];
}
- (void)instanceMethod
{
_number = 123;
std::cout << _number;
}
#end
int main(void)
{
MyClass* foo = [MyClass newInstance];
[foo instanceMethod];
return 0;
}
is roughly equivalent to this C++ code:
class MyClass
{
int _number;
public:
static MyClass* newInstance();
void instanceMethod();
};
MyClass* MyClass::newInstance()
{
return new MyClass();
}
void MyClass::instanceMethod()
{
_number = 123;
std::cout << _number;
}
int main(void)
{
MyClass* foo = MyClass::newInstance();
foo->instanceMethod();
return 0;
}
That example also illustrates one of the differences between class methods and static methods.
+newInstance will be inherited by subclasses and will always work correctly (it will always return an instance of a subclass). It can also be overridden by a subclass.
Static methods like MyClass::newInstance() cannot be inherited or overridden. It will always return an instance of MyClass.
So when you're porting code between Objective-C and C++ there are cases when you cannot use static methods in place of class methods. But for most cases, C++ static methods are a fine replacement.
class SomeClass {
public:
static void someMethod();
};
The equivalent of class methods in C++ would be static functions.
static return_type function_name(parameters);
Just like in Objective-C, in static functions you cannot reference instance variables (since there's no instance), only static variables.
For example.
class A{
public:
static void doIt();
};
Then you can call function doIt with:
void main()
{
A::doIt();
}
Objective-C has implicit metaclasses as explored in "What is a meta-class in Objective-C?" article. The full power of metaclasses is not unleashed, however. It would require multiple inheritance support and other technical decisions, as described in famous "Putting Metaclasses to Work" book. That was probably too complex for Objective-C authors, so they decided to hide metaclasses in Objective-C.
Objective-C targets Objective-C runtime (obj.dll or libobjc.dylib), and there were C++ compilers (DTS C++, Direct-to-SOM C++) targetting SOM the same way. This makes DTS C++ closer to Objective-C than C++ in its design. I managed to get old Windows DTS C++ compiler running on Windows 8 this way:
Download VAC 3.5 fixpak 9 from IBM FTP. This fixpak contain many files, so you don't even need to full compiler (I have 3.5.7 distro, but fixpak 9 was big enough to do some tests).
Unpack to e. g. C:\home\OCTAGRAM\DTS
Start command line and run subsequent commands there
Run: set SOMBASE=C:\home\OCTAGRAM\DTS\ibmcppw
Run: C:\home\OCTAGRAM\DTS\ibmcppw\bin\SOMENV.BAT
Run: cd C:\home\OCTAGRAM\DTS\ibmcppw\samples\compiler\dts
Run: nmake clean
Run: nmake
hhmain.exe and its dll are in different directories, so we must make them find each other somehow; since I was doing several experiments, I executed "set PATH=%PATH%;C:\home\OCTAGRAM\DTS\ibmcppw\samples\compiler\dts\xhmain\dtsdll" once, but you can just copy dll near to hhmain.exe
Run: hhmain.exe
I've got an output this way:
Local anInfo->x = 5
Local anInfo->_get_x() = 5
Local anInfo->y = A
Local anInfo->_get_y() = B
{An instance of class info at address 0092E318
}
This example does not use metaclasses, it's just for checking DTS C++ compiler.
Metaclasses in SOM are explicit, thus so called "class methods" are no more than "instance methods" of metaclass. Each object belongs to some class, managed by so called class-object created in runtime. Class-object is itself an instance of another class, named metaclass. Developer of a class can specify metaclass constraint via IDL or DTS C++ pragma.
If one needs to call method of known at compile time class, one can just reference class-object and invoke its method just like ordinary object which class-object is in essence. Class-object is being referenced via DLL import/export mechanisms, similar to Objective-C.
If one needs to invoke a method of a class that object is belonging to, one needs to invoke somGetClass() to get class-object, typecast it to metaclass type and invoke desired method. In DTS C++ one should probably not need to do redundant typecasting, but I am not expert in IBM DTS C++ properties.

porting C++ library to .NET

I have this simple library written in C++ (source code included)
struct MyStruct
{
char message[ 90 ];
int t;
};
enum MyEnum
{
MY_ENUM_1, MY_ENUM_2
};
class IEvent
{
public:
virtual ~IEvent() {}
virtual void event1( time_t ) = 0;
virtual void event2( MyStruct s ) = 0;
virtual void event3( MyEnum e ) = 0;
};
class Impl;
class MY_API Controller
{
public:
Controller( IEvent* eventListener );
~Controller();
void addListener( IEvent* eventListener );
void removeListener( IEvent* eventListener );
void f1( MyEnum e );
void f2();
private:
Impl* mImpl;
};
The code is implemented in C++11. I need to port this code to .NET.
I thought that a good choice can be C++/CLI but after lots of google I didn't find nothing.
Does someone know how to port this code in C++/CLI? I am able to build all the library in C++/CLI but the library doesn't export any symbols.
Edit1
The library is huge and a re-write in other language is too expensive.
If you want to port this code to .NET, to be used in other .NET languages, such as C#, then you're going to want to re-work how this library does things. Regardless of what language you choose to implement in, if your goal is to be consumed by other .NET languages, you should switch to the .NET paradigms.
For example: currently, you have an abstract class named IEvent. You could create a .NET interface named IEvent, and implement it the same way, but that's not how you do things in .NET. Instead, you'd want to define 3 delegate types, and have your Controller class define 3 events of those delegate types. Instead of addListener and removeListener, each of the events would have add and remove methods (accessed through += and -=).
delegate void Event1Handler(object sender, DateTime data);
delegate void Event2Handler(object sender, MyStruct data);
delegate void Event3Handler(object sender, MyEnum data);
public class EventExample_Controller
{
public event Event1Handler Event1;
public event Event2Handler Event2;
public event Event3Handler Event3;
}
As for the language to use, my initial response would be "C# if you can, C++/CLI if you have to". You haven't said what this library does, it may not be easy, or even possible, to do it in C#. But if you can do it in C#, then you'll get the benefits that language provides: Many of the benefits have equivalents in C++/CLI (e.g., linq query syntax can be represented with regular syntax, extension methods can be called as regular static methods, everything using the async keyword can be done with Tasks and a crapload of state variables), but some are C# only (e.g., having one assembly that works in 32-bit and 64-bit mode).
As for your try to compile the library as-is in C++/CLI, you need to mark the classes as managed classes. Change the classes to public ref class, and the enums to public enum class, and that'll create them as managed. Your next step will be to switch all your pointers to your own classes from unmanaged pointers (*) to managed references (^), and use gcnew instead of new for them.

SWIG C++ bindings with callback

I am writing some SWIG/Python bindings for some C++ code. This is for what is called the Kinect Accidental API, I have the motor and led functions working. The callbacks to the Listener class which parse and populate the RGB and Depth buffers do not seem to get called from SWIG. The data capture threads evidently start up and start hogging the CPU, but no debug lines from the callback come through. What would be better way to populate data buffers and easily access them from python ?
class KinectListener
{
public:
virtual ~KinectListener(){};
virtual void KinectDisconnected(Kinect *K) {};
virtual void DepthReceived(Kinect *K) {};
virtual void ColorReceived(Kinect *K) {};
virtual void AudioReceived(Kinect *K) {};
};
Here is the listener class with the virtual methods, can the Python wrapped version of this class be used to inherit listeners for the c++ class ? I added a minimal listener in C++ and now the remaining work is to access the arrays efficiently with typemaps. Currently I am using this naive typemap
%typemap(out) unsigned short [ANY] {
int i;
$result = PyList_New($1_dim0);
for (i = 0; i < $1_dim0; i++) {
PyObject *o = PyInt_FromLong((long)$1[i]);
PyList_SetItem($result,i,o);
}
}
Better options ?
There is a way using the directors feature.
Enable it for your KinectListener proxy, one line of code :
%feature("director") KinectListener
Then you can inherit from KinectListener class in python code and define your functions.
By coincidence, I happen to be looking into callbacks with SWIG at the moment.
The SWIG 2.0 documentation says this:
SWIG provides full support for function pointers provided that the callback functions are defined in C and not in the target language. ... However, existing C functions can be used as arguments provided you install them as constants. One way to do this is to use the %constant directive like this ...
I'm planning to write a C callback with hand-written JNI to call into Java. If there's another way, I would also love to hear it.

iPhoneOS: using detachNewThreadSelector method inside a C++ class method

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.

Plain C callback function pointer as part of iPhone delegate protocol?

Trying to integrate plain C/C++ code into iPhone project as an external static library. So far so good, but now I'm stuck at a point, where I need to register library callbacks. The library should notify my iPhone application, when something happens. Seems like a good place to define a Delegate.
...but the library is expecting C function pointers for callbacks. How do I define those in Objective-C, how do I use those as part of delegate pattern?
Sorry, really can't give sample code. Here's something bit similar: first interface I got to use to register, followed by definitions of callbacks.
registerCallBack(&aCBack, &bCBack, &cCBack, &dCBack, &eCBack);
typedef void (aCBack)(uint32_t magic);
typedef void (bCBack)(const NewData* newData);
typedef void (cCBack)(uint32_t value, const std::vector<DataStuff*>* stuff);
typedef void (dCBack)(uint32_t value, const SomeData* data, const std::string text, uint32_t type);
typedef void (eCBack)(uint32_t value, const MoreData* more);
...oh btw, one of the problems is that each Objective-C class method has two hidden arguments. Not sure how to deal with that at all. Besides changing interface of that external library.
You need to use C++/C interfaces for the callbacks which then internally delegate the call to your Objective-C code. Where the callback registrations allow you to pass in user-data of sufficient size, you can conveniently pass something that identifies your context like in this answer.
Callbacks that don't get passed any context have to call a class method of your Objective-C part anyway.
You have to use plain C functions for this, but you can call through to your delegate object from them as long as you're compiling as Objective-C:
// need to have a reference to the object, of course
static DelegateClass* delegate = NULL;
// call at runtime with your actual delegate
void setCallbackDelegate ( DelegateClass* del ) { delegate = del; }
void callbackA ( uint32_t magic )
{
[delegate handleCallbackA:magic];
}
// and so on...
[Update: as gf points out, you can use a class method and avoid the need for setCallbackDelegate.]