Trouble with adding C++ objects to Objective C collections (NSSet) - c++

I'm busy implementing ZXing with a QRCodeReader into my project.
QRCodeReader is mainly C++ and my project objective-C.
I have managed to implement it properly so I can use the QRCodeReader objects into my objective-C implementation (.mm file).
But now I need to pass this C++ object to the zxWidController.reader property.
This means I will have to set the C++ object into an NSSet Object.
QRCodeReader* qrcodeReader = new QRCodeReader();
NSSet *readers = [[NSSet alloc ] init];
[readers setByAddingObject:(id)qrcodeReader];
widController.readers = readers;
[readers release];
The code above does the trick. I casted the C++ object to (id) and now it compiles properly. But is this the proper way to do it?
Is this manner of programming the proper way to do this?
Are there any other / better ways to achieve my goal?

A C++ type is not an Objective C type. You cannot send it messages, in particular retain and release, which NSSet does. There's an Objective C type of the same name that you want to use. (I'll update my other answer).

The code above does the trick. I casted the C++ object to (id) and now
it compiles properly. But is this the proper way to do it?
No. You can't just make an arbitrary pointer into a valid Objective-C object pointer by casting it to id.
Is this manner of programming the proper way to do this?
Again, no.
Are there any other / better ways to achieve my goal?
You can try any of the following:
Redefine your zxWidController class to take a pointer to a C++ object instead of an Obj-C object.
Wrap qrcodeReader in a NSValue.
Take a look at NSPointerArray as a replacement for NSSet. Definitely read the docs before you try to use it -- you have to configure it's memory management policies to do the right thing for the type of pointer you're storing.
Minor nitpick: Forgetting for a moment about the fact that qrcodeReader points to a C++ object, it seems silly to create an empty set just so that you can add an object to it. If you were going to use an Obj-C set, then either create it using +setWithObject: or use NSMutableSet instead.

Related

How to store get a correct Glib::RefPtr to a non-widget using Gtk::Builder

It is rather simple to get a Glib::RefPtr to any widget by using get_widget function of Gtk::Builder, but when it comes to getting other objects the corresponding get_object function returns Glib::Object, which is not easily convertable to the needed class (such as Gtk::TreeView).
What is the appropriate way of doing that?
It would be best to use Glib::RefPtr<TheDerivedype>::cast_dynamic(object) .
However, Gtk::TreeView (which you mention in your question) is a Gtk::Widget, so you would use get_widget() instead of get_object().
If you meant, Gtk::TreeModel, well, defining GtkTreeModels in Glade, for use in gtkmm C++ code, is something that might work since we added some fixes for that in gtkmm recently:
https://bugzilla.gnome.org/show_bug.cgi?id=742637
But it's not something that we generally expect to work - many C++ developers would prefer the static type safety of defining the DataModel structure completely in code, and not relying on a translation between C and C++ types. For instance: https://developer.gnome.org/gtkmm-tutorial/stable/sec-treeview-model.html.en#treeview-model-liststore
Glib::RefPtr has a static template function which allows one to do what is needed. This function is logically called cast_static.
The sample code can be:
treeStore =
Glib::RefPtr< Gtk::TreeStore >::cast_static( builder->get_object("treestore1") );

How to assign dispatch_queue_t to variable in a structure

I'm still relatively new to Objective C and easily confused by the various types. I am using code from the SquareCam sample project, incorporated into a larger project. It works fine, but now I want to save the videoDataOutputQueue, which is of type dispatch_queue_t so that I can use it elsewhere in the project. It has to pass through some C++ code before finally ending up back in Objective C code. Therefore I am trying to add it to a structure that I already have, as a void * (void *videoDataOutputQueue;)
However, I have not found the right way to assign it without getting a EXC_BAD_ACCESS runtime error. Since dispatch_queue_t is a C++ object, can't I just use it's address?
declared in the interface for squarecamviewcontroller:
#interface SquareCamViewController : UIViewController <UIGestureRecognizerDelegate, AVCaptureVideoDataOutputSampleBufferDelegate,UIActionSheetDelegate>
{
AVCaptureVideoPreviewLayer *previewLayer;
AVCaptureVideoDataOutput *dataOutput;
AVCaptureVideoDataOutput *videoDataOutput;
dispatch_queue_t videoDataOutputQueue;
<other stuff>
}
later in the code:
- (void)setupAVCapture
{
<other stuff from the sample code>
MYSTRUCT myStruct = (MYSTRUCT)struct; // make a pointer to the structure
myStruct->videoDataOutputQueue = (void *)videoDataOutputQueue; <<<- bad access here at runtime
<other stuff>
}
Clearly this is not the right way and I don't understand what I am doing. I have some hints from other posts but I'm missing something.
Thanks,
Ken
You have made your question unnecessarily difficult to understand because the "code" you've presented has syntax errors. It's clearly not your real code, so we can't guess what's really supposed to be happening. For example, you use the struct reserved keyword as though it were a value.
Given where you say the bad access occurs, this has nothing to do with the dispatch queue. It looks like your myStruct variable is supposed to be a pointer to a structure of some kind but is just a garbage pointer. So, the attempt to assign a value to one of its fields ends up writing to an invalid memory address. It doesn't really matter what the nature of the field is.
The problem is apparently exactly in the code you omitted as "<other stuff from the sample code>". So, you need to show that. Indeed, you need to show your real code.
Beyond that, dispatch_queue_t is a C type. It's not specific to Objective-C. Therefore, you can use it across all C-based languages. There's no need to use a void*.
A dispatch queue, like all dispatch objects, is reference counted. If you're keeping a long-term reference to it, you need to make sure it stays alive. So, you need to retain it with dispatch_retain(). Likewise, you need to release it when you're done with it using dispatch_release(). (Don't forget to release the old value when you replace a reference you're keeping with another.)

passing pointers or integral types via performSelector

I am mixing Objective-C parts into a C++ project (please don't argue about that, its cross-platform).
I now want to invoke some C++ functions or methods on the correct thread (i.e. the main thread) in a cocoa enviroment.
My current approach is passing function pointers to an objective-c instance (derived from NSObject) and do performSelector/performSelectorOnMainThread on it.
But the performSelectors expect objects as their arguments, so how would one usually wrap this?
Example:
typedef void(*FnPtr)(void*);
FnPtr fn;
[someInstance performSelector:#selector(test:) withObject:fn];
... where test is declared as:
- (void)test:(FnPtr)fn;
Have to add that i only started with objective-c this week, so if there is a better way i'd be also glad to hear about it.
Also note that i don't have any access to the main loop or any application objects because the project is an browser plug-in (currently only targetting Safari on the mac).
As answered by smorgan here, NSValue is designed as a container for scalar C & Objective-C types:
- (void)test:(NSValue*)nv
{
FnPtr fn = [nv pointerValue];
// ...
}
// usage:
NSValue* nv = [NSValue valueWithPointer:fn];
[someInstance performSelector:#selector(test:) withObject:nv];
I am not sure if my solution is considered sane / correct -- I do however frequently pass pointers by simply typecasting them to (id)s. That is dirty but does work for me. The possibly cleaner way would be using NSValue.

Objective C in C++ – Out of Scope

I have a little problem with the WOsclib. Not particularly with the library, it's more the callback function. The listen to specific osc commands i have to put up some callback method like
void TheOscStartMethod::Method(
const WOscMessage *message,
const WOscTimeTag& when,
const TheNetReturnAddress* networkReturnAddress)
{
std::cout << "Got the start signal";
start.alpha = 1.0;
}
start is IBOutlet UIImageView.
But the compiler says me, that start is out of scope. If I try to access start in obj-c code, it works like it should.
How can i get my Objective C Objects into the c code or at least call a objective-c function.
Thank you
Make the file an objective C++ file with extension .mm Then you can call object C and C++ objects in the same code.
XCode will call the correct compiler from the file extension (ie adding -x objective-c++ to the compile command)
Not that C++ and objective C are different languages and do not understand each others objects so to move data between them you will need to convert the data to a C type e.g. void, char int and pointers to them.
It sounds like start is an instance variable belonging to some Objective-C object and you're trying to access it just by writing its name from a C++ object. If this is the case, it should be pretty obvious why it won't work: The C++ object doesn't know anything about start. The solution is to somehow give the C++ object a reference to the Objective-C object that owns start.
You'll have to make the start object available to your other code.
You can pass it, you can pass the portions you'll be using, you can create an API for the two code bases to use. There are other options as well, all depending on precisely how you wish to use the various objects
The Solution:
I don't know if this is the best way to do it, but it works.
There must be an empty c object, which later will become our objective c object that holds all the stuff we want to access.
static gsSearchForIp* delegate = NULL;
We must define a function to set the objective c object
void setCallbackDelegate(gsSearchForIp* del)
{
delegate = del;
}
And then call it. ( I called it in the initWithFrame method)
setCallbackDelegate(self);
Now i can call a method with [delegate methodName:firstPara] in my c++ method. In this function i have access to all my stuff that I need from the gsSearchForIp class.

Is it best practice to use COM properties or COM setters and getters in C++?

I am relatively new to development within COM, and I was wondering what the community standard was for access of COM object properties. I have seen both of the following conventions in code:
comObjectPtr->PutValue(value);
and
comObjectPtr->Value = value;
and both seem to work, but I was wondering if there was an inherent advantage or disadvantage to either approach and why.
If I remember correctly, using the property assignment will throw an exception vs. a HRESULT returned in the setter if there is a problem.
Same thing is true of the getter method calls vs. property.
A "benefit" of using the property is that you can use the prop-get values directly instead of having to declare a variable and getting it before using.
You're talking about the smart wrapper classes created with #import, right?
PutValue() is more explicit as to what you're doing; "Value = " is easier to use but it can have "hidden" side-effects if the put function does something other than a straight assignment. As I understand it, the two are equivalent, just different syntaxes.