CoreBluetooth delegate method never called (objective c++) - c++

I have a unique use case where I am using CoreBluetooth in my C++ application. There are a lot of old tutorials on CoreBluetooth implementation for objective c and my code looks familiar to this. My problem is that after initializing CBCentralManager, centralManagerDidUpdateState is not being called.
wrapper.h file for c++
// this file defines c++ functions to be used in the .mm file
void *get_object();
.h file for objective c
#import "wrapper.h"
#interface MyObject : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate>
#property(strong, nonatomic) CBCentralManager *centralManager;
- (id)init;
- (void)initialize_manager;
#end
.mm file
// declared in wrapper.h, this is a c++ method to return a void pointer to MyObject
void *get_object() {
void *obj_ptr = [[MyObject alloc] init];
return obj_ptr;
}
// this is the objective c code
#implementation MyObject
- (id)init {
self = [super init];
if (self) {
// this is where the central manager should be created
[self initialize_manager];
}
return self;
}
- (void)initialize_manager {
_centralManager = [[CBCentralManager alloc] initWithDelegate:self
queue:nil
options:nil];
}
// this should get called immediately after initialize_manager
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
std::cout << "this never gets called" << std::endl;
NSLog(#"this never gets called");
.cpp file to test it
void *p = get_object();
Summary of code:
In my .cpp file I am calling get_object() which initializes a new MyObject and returns a void pointer to it. When initializing a new MyObject, it calls initialize_manager() which should (but currently doesnt call) call centralManagerDidUpdate.
Previous issue I found of centralManagerDidUpdateState not being called:
Their problem was they didn't assign the central manager to an instance variable. However, I did so doesn't seem like that applies to me.
Not sure if this is a problem with objective-c++ not handling delegates properly, or if storing MyObject as a void* pointer messes with some internal magic.
Also maybe it is because my program exits too soon? Every implementation of CoreBluetooth I've seen is used in a ViewController, can I replicate the non terminating aspect of a view controller in C++? Maybe it's something to do with async issues? Would appreciate any pointers!
update 1: I think CoreBluetooth may be sharing the same thread as the main c++ application

Posting this short answer for now, will edit as a get cleaner iterations. The problem is that the objective c library (CoreBluetooth) needed to be run on a different thread than my main application.
stay tuned for code implementation

Related

Addressing segfaults and other problems due to unexpected library behavior?

I've been running into problems with a C++ program that I've been working on recently. Specifically, I've been working on a program that uses Qt's GUI framework and I've been running into errors that seem to be related to double-deletion of pointers and exception handling. The issue is that I feel like the API that I'm using works in a way that isn't exactly predictable and because of that, I'm running into a lot of errors that seem counter-intuitive. I'm not the most experienced C++ programmer in the world, so maybe there is some overall strategy for working with new APIs that I'm missing..
Here's an example: I typically always try to delete objects that I dynamically allocate with inside the same class. In other words, if I populate a pointer using the new keyword within a class' constructor or init function, then I usually make sure to delete the contents of that pointer in the class' destructor.
Here's an simplified example of the class definition for the class that was giving me problems [MyProject.h]:
#ifndef MYPROJECT_H
#define MYPROJECT_H
#include "QObject.h"
class QGuiApplication;
class QQmlApplicationEngine;
#define MYPROJECT MyProject::getInstance()
class MyProject : public QObject
{
Q_OBJECT
private:
explicit MyProject(QObject *parent = 0); //singleton..
MyProject(MyProject const&); //uncopyable..
void operator=(MyProject const&); //unassignable..
QGuiApplication * QtGUI;
QQmlApplicationEngine * QmlAppEngine;
public:
~MyProject(void);
/* Globally available function to get MyProject's singleton instance.
* You can use the "MYPROJECT" preprocessor macro for shorthand. */
static MyProject & getInstance(void)
{
static MyProject instance;
return instance;
}
int init(int argc, char * argv[]);
int exec(void);
signals:
public slots:
};
#endif
This is what my simplified main.cpp looks like:
#include "MyProject.h"
int main(int argc, char * argv[])
{
MYPROJECT.init(argc, argv);
return MYPROJECT.exec();
}
Here's the ctor and init() that I initially had for that class [MyProject.cpp]:
MyProject::MyProject(QObject *parent) :
QObject(parent) ,
QtGUI(NULL) ,
QmlAppEngine(NULL)
{
}
MyProject::~MyProject(void)
{
//segfault: debug points to both of these..
if (QtGUI) delete QtGUI;
if (QmlAppEngine) delete QmlAppEngine;
}
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//segfault: debug points to this..
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
else return 1;
}
int MyProject::exec(void)
{
return QtGUI->exec();
}
So, my plan was: ctor initializes pointers to NULL, init() populates those pointers with new objects, and if those pointers are not null the dtor cleans them up with delete. But this code crashes with 2 segfaults, but even though I think I've narrowed it down, I'm not sure I understand why they're both happening.
(1) Segfault #1 is a crash on startup that points to the "QmlAppEngine->load()" call inside the init(). I was able to prevent the crash from occurring by wrapping that function call in exception handling code like this:
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//exception handling prevents crash..
try
{
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
catch(int e)
{
std::cout << "Exception: " << e << std::endl;
return 1;
}
return 0;
}
else return 1;
}
I'm not very familiar with exception handling, as most of the code I've written so far has used int return-code style error handling. I'm guessing that the load function can throw an exception in certain situations, and not handling them can cause a crash. The program stopped crashing on start-up once I made this change, but strangely, it didn't seem to actually throw an exception as my 'cout' never output anything.. Something else that I don't understand is that this code is called without any exception handling code in the default setup for brand new Qt Projects that Qt Creator makes - for example, this is what you see when you start a new QtQuick2 project in QtCreator IDE:
#include "QGuiApplication"
#include "QQmlApplicationEngine"
int main(int argc, char * argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine();
//default Qt file calls this without issue though..
engine.load(QUrl( QStringLiteral("qrc:///MyQml.qml") );
return app.exec();
}
The only major different that I can see here is that the default code uses objects instead of pointers to objects. But, in this case, load runs fine without exception handling code and there is no segfault..
(2) The next issue is caused when my dtor calls the delete keyword on those two pointers. If I comment out those two lines, the program runs fine and closes without crashes or issues. This leads me to believe that the API has made these objects delete themselves later, which is causing a segfault due to double-deletion when I also explicitly call delete. But, in general, how can one know if the API that they're using is taking care of object deletion internally? And, if I can't tell whether or not an API specified object is being deleted automatically, should I take any extra measures (i.e.: use some kind of smart pointer, etc.)? Typically I make the assumption that I should delete any dynamically allocated objects in the destructor of the same class, but clearly that can backfire in situations like this.
So what steps can I take to work with the APIs that I use in a way that (a) prevents bugs and (b) allows me to make sure that resources are being freed correctly and exceptions are being handled?
It's hard to find the exact location of error by seeing the sample code you provided, your application must have large code base and does many things with memory. Qt is a well designed and fully documented framework (though some documentation are misleading or outdated), I suggest you to read properly the documentation about a specific item if you have confusion. Here are some general issues I guess you should know/consider when using Qt:
When creating an object on the heap of class that inherits QObject, if you pass a parent ( another QObject) in the constructor, then the child object is owned by parent and memory will be freed automatically by the parent object.
QObject is NO_COPYABLE, so if you inherit from it, you don't need to make copy ctor/assignment operator private. The compiler generated versions of these methods calls parent version (here QObject), hence your class is automatically un-copyable/assignable.
new by default throws bad_alloc exception if it fails instead of returning NULL. So either you use try-catch or change default behavior by using no_throw version of new (new(std::nothrow)), it will return nullptr on failure.
deleteing a NULL pointer will not cause any problem. However, if the pointer points to arbitrary location / contain garbage value, deleteing it will result in segfault.
By default engine.load is not used with exception handler, so there is a high chance it does not raise exception. Look closely in other areas of your code.

Call Objective-C method from C++ method

Hello I know that this problem was discussed several times, but I have feeling that no other explenation works for me. Maybe it isn't possible but... at the moment I have mm file it looks like (init methods/ header file) obj-c except few C++ methods (library live555 which I use is written in C++), and I can call C++ methods form obj-c just fine. But when I want call obj-c in c++... then I got error. I know self isn't know. But how I can move aroud it? I try with 2-3 tuts but all of them assume that obj-c method isn't called inside that obj-c++ class.
My Obj-C++ class (.mm file)
#interface testSender : NSObject{
#private
NSMutableArray *_buffors;
}
+(id)voiceSender;
//Function to invoke
-(bool)continueSendBuffer;
#end
#implementation testSender
#synthesize address=_address,port=_port;
UsageEnvironment* env;
+(id)voiceSender{
return [[self alloc]init];
}
- (id)init
{
self = [super init];
if (self) {
[self initRTPProt];
_buffors = [NSMutableArray array];
}
return self;
}
-(void)initRTPProt{
//init protocol
}
void afterPlaying(void* clientData); // forward
void afterPlaying(void* /*clientData*/) {
// We and stream and now I want check if it's some other streams to send so normaly I should call
[self continueSendBuffer];
}
-(bool)continueSendBuffer{
if ([_buffors count] == 0) return false;
NSData *nextBuffer = [_buffors objectAtIndex:0];
[_buffors removeObjectAtIndex:0];
[self sendNextBuffer:nextBuffer];
return true;
}
-(void)sendNextBuffer:(NSData*)buffer{
// Send next buffer
/setting sessionState..
// Start the streaming:
*env << "Beginning streaming...\n";
// Method afterPlaying will be called after ther will be nothing to send
sessionState.sink->startPlaying(*sessionState.source, afterPlaying, NULL);
env->taskScheduler().doEventLoop();
}
#end
At c++ method void afterPlaying(void*) when I want use [self continueSendBuffer] then I got error Use of undeclared identifier 'self'.
Solved
Chuck did great job and explain me how Objective-C++ works. Read it!
Basically you just can't call obj-c method in "c++ method" (I know there are free floating methods) with out passing to them self pointer.
I have to modify a bit startPlaying call and now in third argument I pass self pointer
Also method afterPlaying had to been change so now she can use clientData pointer. Throught this I can call continueSendBuffer.
startPlaying
sessionState.sink->startPlaying(*sessionState.source, afterPlaying, (__bridge void*)self);
afterPlaying
void afterPlaying(void* clientData) {
[(__bridge NXVoiceSender*)clientData continueSendBuffer];
}
Objective-C++ does not unify C++ classes and Objective-C classes. It allows you to mix Objective-C code and C++ code, but the two object models are still completely separate — it basically just uses C++ where C would be used in normal Objective-C. What you're calling "C++ methods" there are actually just free-floating functions, because an Objective-C class definition isn't a special context in C++. They are not methods of the class.
You'll somehow need to keep a pointer to the object in question and get that into the afterPlaying() function (and also keep the object alive long enough to be referenced when afterPlaying() is called). I'm not familiar with the library, but that clientData parameter looks promising.
The type of the second argument of startPlaying is std::function? If so, you can pass a Block instead of C++11 lambda for that as the following with "C++ Language Dialect" to "C++11".
__weak testSender *self_ = self;
sessionState.sink->startPlaying(*sessionState.source, ^(void *){
// We and stream and now I want check if it's some other streams to send so normaly I should call
[self_ continueSendBuffer];
}, NULL);

Handling UIAlertView delegate from C++

I have a C++ project on iOS. It mostly uses C++, except for some tasks that require Objective-C. For instance, showing a UIAlert.
So I call the UIAlert from C++. How do I get the result and know what was the button tapped by the user?
This is the implementation of the C++ class calling to Objective-C
void iOSBridge::iOSHelper::ShowAlert()
{
[IsolatedAlert showAlert];
}
And here I have the Objective-C implementation:
+ (void)show{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message: #"hello"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[alert show];
[alert release];
}
+ (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
}
Is there any way to call C++ again from clickedButtonAtIndex delegate?
Thanks.
There's nothing preventing you from calling a C++ class from an Objective C one. You'll need to provide your Objective C class with some sort of a handle to the C++ class, which it will need to store as an instance variable. Then you can do whatever you want with it.
That's going to be awkward to accomplish while you're only using class methods like you are. It'll be better to use instance methods, and then create an instance from the C++ side, provide the instance with a handle, then send messages to the instance instead of the class.
Make the extension of this class as .mm
Then have an static var YourClaas *delegate; in it
+ (void)showAlertWithDelegate:(YourClass*)del{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message: #"hello"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
delegate = del;
[alert show];
[alert release];
}
+ (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
del->buttonClickAtIndex(buttonIndex);
}
and define void buttonClickAtIndex(int index) method in your cpp file

Handle Cocoa setAction message in Objective-C++

How do you handle the setAction message in Objective-C++? (Not Objective-C.)
For example, suppose I have:
my_class.mm
NSSegmentedControl *segmented = [[NSSegmentedControl alloc] init];
[segmented setSegmentCount:5];
// etc.
[segmented setAction:???];
Application: I am programming in Qt (C++) and need a wrapper around some Cocoa widgets I want to use directly. I am inheriting from QMacCocoaViewContainer but can't figure out how to handle the "clicks" of the NSSegmentedControl I am wrapping. Eventually this will emit a standard Qt signal.
action is just a selector - it is used in tandem with target. so write an objc method for target+action which calls through or does what you really want. actions' arguments are the sender, but you can omit that if you don't need it. the sender will be whatever is sending the message (e.g. the control). it's no different in ObjC++ - this has to be wrapped in an objc method because the target must be an objc object.
so it would look like this:
obj.action = #selector(pressDoStuff:);
and the method is:
- (void)pressDoStuff:(id)sender
#Justin has the right answer; I'll accept it, but also include the final solution in case it helps others. The trick is you need a proxy class, as #smparkes noted.
Ignoring the .h files for brevity:
mac_control.mm
MacControl::MacControl(QWidget *parent) : QMacCocoaViewContainer(NULL, parent) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSSegmentedControl *segmented = [[NSSegmentedControl alloc] init];
// Set up NSSegmentedControl...
// The proxy class marshalls between Objective-C and C++.
proxy_ = [[MacControlProxy alloc] init];
[proxy_ setTarget:this];
[segmented setTarget:proxy_];
[segmented setAction:#selector(handleToggle:)];
setCocoaView(segmented);
[segmented release];
[pool release];
}
MacControl::~MacControl() {
delete proxy_;
}
void MacControl::TriggerAction(int index) {
// Trigger the action in Qt/C++.
}
mac_control_proxy.mm
#implementation MacControlProxy
- (id)init {
[super init];
target_ = NULL;
return self;
}
-(void) handleToggle: (id)sender {
if (target_) {
target_->TriggerAction([sender selectedSegment]);
}
}
-(void) setTarget: (MacToolbarButtonControlImpl*)target {
target_ = target;
}
#end
I'm following up on Dave Mateer's answer (which was super helpful!).
I was having issues setting the C++ target (from within a objective-C++ class) and used [NSValue valueWithPointer:theTargetCxxClass] to pass the target to the Proxy.mm class.
So, inside of my Objective-C++ class, rather than doing this:
[proxy_ setTarget:this];
I did this:
[proxy_ setTarget:[NSValue valueWithPointer:this]];
or
[proxy_ setTarget:[NSValue valueWithPointer:ptrToMyCxxObject]];
And doing this got rid of an error about passing a C++ class (which does not extend type "id") to the Objective-C++ proxy class.
Inside of the proxy class, you then need to use NSValue's pointerValue method and then cast back to the C++ class in order to send a message to it.
-(void) myButtonAction: (id)sender {
((MyCxxClass*)[target pointerValue])->someMethodInMyCxxClass();
}
I first was alerted to the "valueWithPointer" trick in this post.

C++: indirect invocation of `delete this` in event driven system (e.g. in GUI application)

I was working for a while with different C++ GUI frameworks (e.g. Qt, wxWidgets, also some proprietary) but cannot decide for myself regarding the topic described below.
As discussed in several questions/answers here, direct use of delete this is valid in C++ (as long as you don't dereference this any more), but it is in most cases not good idea.
But in some cases, object invokes its destructor indirectly. This situation specifically often arise in event drive systems (GUI applications come to mind first).
class Kernel {
public:
void Start() {
_window = new Window();
}
void OnCloseButton() {
if (_window) {
_window->Close();
delete _window;
_window = NULL;
}
private:
MyWindow * _window;
};
class MyWindow
{
public:
MyWindow(Kernel & kernel) : _kernel(&kernel) {
Connect(my_button_close_event, this, OnCloseButtonClicked);
}
OnCloseButtonClicked() {
// This call actually calls destructor of this object.
_kernel->OnCloseButton();
// If we access any fields of Window here, we're going to have problems
}
private:
Kernel * _kernel;
};
Notice: I did not try to compile the code - it may have typos or bad practices. But it should illustrate the idea.
So, the question is: Is it OK to do something like in the example above: the handler of the event calls some other function (method of its owner), which indirectly deletes this?
Or should I better make the Kernel class event aware and connect the event from the button directly to the method in the Kernel and then we do not have this situation of indirect call to delete this.
Thanks in advance.
It's possible to do so since the Window instance is created by the Start() method but it's a bad practice in Object Oriented Programming.