I am trying to create a function in Objective-C for monitoring a pointer declared on my C/C++ side of code by using KVO. Is there a way to do this?
To elaborate. I have a C object pointer. I pass that pointer as void* through my bridge function down to Objective-C side of the code.
Is it possible to use the pass-down void* to set up KVO and notify via:
-(void)observeValueForKeyPath:(NSString *) keyPath of Object:...
when the C object pointer is modified by C side of code?
KVO, with its ability to just observe a property and automatically get notifications every time it changes, seems like magic, but really all it is is Apple automatically changing your property's setter from this:
- (void)setFoo:(Foo *)newFoo {
self.foo = newFoo;
}
into this:
- (void)setFoo:(Foo *)newFoo {
[self willChangeValueForKey:#"foo"];
self.foo = newFoo;
[self didChangeValueForKey:#"foo"];
}
The will and didChangeValueForKey: methods are what cause the KVO system to check for observers for the property, and notify them if there are any. The automatic substitution of the setter is done by taking advantage of the extremely dynamic nature of Objective-C, which makes it relatively simple to patch methods and alter them at runtime (this is, incidentally, why the dynamic keyword is needed to implement KVO properties in Swift). Of course, these dynamic features do not exist in C or C++.
What you will need to do, then, is to have your C code define two callbacks; one which the C code will call before changing the value, and another which it will call afterwards. Once you've got this set up, have the Objective-C side register these callbacks somewhere in your setup process, and have the callbacks call the willChangeValueForKey: and didChangeValueForKey: methods. Once you've done this, you should be able to observe the property using the normal KVO methods.
Related
If I am given a pointer to an object and I need to pass one of that object's methods as an argument to another function, is that possible?
A very simplified example would look like this:
void consumeAFunction(Function func) {
auto value = func();
// do some stuff //
}
void main(Object *pointerToObject) {
consumeAFunction(pointerToObject->someMethod)
}
I've tried the following, but I think my understanding of pointers and references is flawed. I'm 3 weeks old in my c++ journey.
Object someObject = pointerToObject and Object someObject = *pointerToObject
The specific context of the question is that I have a pointer to an object created by some other library and I need to use QtConcurrent::run on that object's methods.
Additional context
consumeAFunction is QtConcurrent::run
Function func is a method of an Engine that simply performs some logic. I am handed a pointer to Engine by a third party library.
I cannot avoid using a pointer to Engine, because it is all I am given to work with.
As much of the specific code as I am allowed to show:
// engine is the pointer to someObject:
auto engine = lui::QueryInterop<wise::Engine>(lui::GetLUI());
if (engine) {
connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded);
// This is the call to consumeAFunction (qtconcurrent::run)
m_modelsLoadedFuture = QtConcurrent::run(engine->loadPytorchModels);
m_modelsLoadedWatcher.setFuture(m_modelsLoadedFuture);
Because this is a Qt question, I highly recommend you get an understanding of QObject and QMetaObject::invokeMethod().
Because QObject is pre-processing via the moc-compiler, a lot of public interfaces, such as properties, methods are exposed in such a way that the object's properties and methods can be inspected at runtime by another plugin and that it doesn't need to know or have access to the header files. This is why something like QMetaObject::invokeMethod() can work because it has access to the metadata.
Alternatively, if you are using Javascript a lot in QML, you may be interested in passing a Javascript callback function to C++. That function is accessible via QJSValue. QJSValue usually is used to hold simple types such as strings and numbers. When it holds more complex Javascript types such as arrays, objects, or functions you can use quite a few QJSValue methods to unlock their capabilities. In the case of Javascript functions you can verify if it is a Javascript function with QJSValue.isCallable() == true and can you can execute it with QJSValue.call(...).
So I am still working on a flexible scripting system for this school project and have come to a road block. The problem is this: I have a script state manager interface that any scripting state will implement (currently implementing lua, but want to be able to add python later). It has pure virtual functions for things such as DoFile, DoString, RegisterObject and RegisterFunction. So the LuaStateManager implements this interface using luaplus classes and encapsulates the LuaState object as it should.
So when an object registers itself with lua and throws all its methods into a metatable I have to do something like this:
metaTable.RegisterObjectDirect(“Move”, (Actor*)0, &Actor::Move);
This would be fine if I had access to the underlying state object in the StateManager interface as it would be getting called from the Actor class itself so the cast could be guaranteed. Unfortunately, I need to somehow pass this info to the LuaState::RegisterFunction method so the I don't have to expose the LuaState object and couple my classes to it. As far as I can see though, there is no way to pass information about which type of class to cast to.
Does any body have any suggestions? I thought about trying to use a templated function to perform the cast, but I know that you can't have function pointers to templates, so that is out the window. Thanks!
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];
}
We're interfacing to some 3rd party COM objects from a C++Builder 2010 application.
Currently we import the type library and generate component wrappers, and then are able to make method calls and access properties in a fairly natural way.
object->myProperty = 42;
object->doSomething(666);
However, we've been bitten by changes to the COM object's interface (which is still being extended and developed) causing our own app to fail because some method GUIDs seem to get invalidated - even if the only change to the interface has been the addition of a new method).
Late Binding has been suggested as a way of addressing this. I think this requires our code to be changed rather like this:
object.OlePropertySet("myProperty", 42);
object.OlePrcedure("doSomething", 666);
Obviously this is painful to read and write, so we'd have to write wrapper classes instead.
Is there any way of getting late binding wrappers generated automatically when we import the type library? And, if so, are they smart enough to only do the textual binding once when the object is created, rather than on every single method call?
When you import a TypeLibrary for a COM object that supports late-binding (when it implements the IDispatch interface), the importer can generate separate wrapper classes (not components) for both static-binding and late-binding.
Adding a new method to an existing interface should not invalidate your code. Methods do not have GUIDs. However, for an IDispatch-based interface, its methods do have DISPID values associated with them, and those DISPID values can be changed from one release to another. Though any respectable COM developer should never do that once an interface definition has been locked in.
After deep investigation of the code and headers generated by the TLIBIMP, this turns out to be fairly easy.
If your Type Library has a class Foo, then after importing the type library, you would typically use the auto-generated smart pointer classes IFooPtr.
{
IFooPtr f;
...
f->myMethod(1,2);
}
You should note that at this point that the bindings are static - that is, they depend not just on the GUIDs of the objects and the DISPIDs of the methods, but on the exact layout of the VTable in the DLL. Any changes that affect the vtable - for instance, adding an additional method to a base class of Foo will cause the method call to fail.
To use dynamic bindings, you can use the IFooDisp classes instead of IFooPtr. Again, these are smart wrappers, handling object lifetimes automatically. Note that with these classes you should use the . operator to access methods, not the indirection -> operator. Using the indirection operator will call the method, but via a static binding.
{
IFooDisp f;
...
f.myMethod(1,2);
}
By using these IDispatch-based wrappers, methods will be dispatched by their DISPIDs, even if the objects vtable layout is changed. I think these classes also give a way to dispatch by function name rather than DISPID, but haven't confirmed the details of that.
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.