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];
}
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(...).
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.
So here's the situation: I'm using C++, SDL and GLConsole in conjunction. I have a class, SDLGame, which has the Init(), Loop(), Render() etc - essentially, it holds the logic for my game class.
GLConsole is a nice library so far - it lets me define CVars and such, even inside my SDL class. However, when defining commands, I have to specify a ConsoleFunc, which is typedef'd as
typedef bool (*ConsoleFunc)( std::vector<std::string> *args);
Simple enough. However, like I said, my functions are all in my class, and I know I can't pass pointer-to-class-functions as pointer-to-function arguments. I can't define static functions or make functions outside my class because some of these ConsoleFuncs must access class data members to be useful. I'd like to keep it OOP, since - well, OOP is nice.
Well, I actually have this problem "solved" - but it's extremely ugly. I just have an instance of SDLGame declared as an extern variable, and use that in my ConsoleFuncs/main class.
So, the question is: Is there a way to do this that isn't stupid and dumb like the way I am doing it? (Alternatively: is there a console library like GLConsole that supports SDL and can do what I'm describing?)
If the only interface you have is that function pointer, then you're screwed.
A member function needs a this pointer to be called, and if you have no way of passing that, you're out of luck (I guess the std::vector<std::string>* args pointer is what you get passed from the library).
In other words, even though that library uses C++ containers, it's not a good C++ library, because it relies on free functions for callbacks. A good C++ library would use boost::function or something similar, or would at the very least let you pass a void* user_data pointer that gets passed through to your callback. If you had that, you could pass the this pointer of your class, cast it back inside the callback, and call the appropriate member function.
in C++, I can easily create a function pointer by taking the address of a member function. However, is it possible to change the address of that local function?
I.e. say I have funcA() and funcB() in the same class, defined differently. I'm looking to change the address of funcA() to that of funcB(), such that at run time calling funcA() actually results in a call to funcB(). I know this is ugly, but I need to do this, thanks!
EDIT----------
Background on what I'm trying to do:
I'm hoping to implement unit tests for an existing code base, some of the methods in the base class which all of my modules are inheriting from are non-virtual. I'm not allowed to edit any production code. I can fiddle with the build process and substitute in a base class with the relevant methods set to virtual but I thought I'd rather use a hack like this (which I thought was possible).
Also, I'm interested in the topic out of technical curiosity, as through the process of trying to hack around this problem I'm learning quite a bit about how things such as code generation & function look-up work under the hood, which I haven't had a chance to learn in school having just finished 2nd year of university. I'm not sure as to I'll ever be taught such things in school as I'm in a computer engineering program rather than CS.
Back on topic
The the method funcA() and funcB() do indeed have the same signature, so the problem is that I can only get the address of a function using the & operator? Would I be correct in saying that I can't change the address of the function, or swap out the contents at that address without corrupting portions of memory? Would DLL injection be a good approach for a situation like this if the functions are exported to a dll?
No. Functions are compiled into the executable, and their address is fixed throughout the life-time of the program.
The closest thing is virtual functions. Give us an example of what you're trying to accomplish, I promise there's a better way.
It cannot be done the way you describe it. The only way to change the target for a statically bound call is by modifying the actual executable code of your program. C++ language has no features that could accomplish that.
If you want function calls to be resolved at run-time you have to either use explicitly indirect calls (call through function pointers), or use language features that are based on run-time call resolution (like virtual functions), or you can use plain branching with good-old if or switch. Which is more appropriate in your case depends on your specific problem.
Technically it might be possible for virtual functions by modifying the vtable of the type, but you most certainly cannot do it without violating the standard (causing Undefined Behavior) and it would require knowledge of how your specific compiler handles vtables.
For other functions it is not possible because the addresses of the functions are directly written to program code, which is generally on a read-only memory area.
I am fairly sure this is impossible in pure C++. C++ is not a dynamic language.
What you want is a pointer to a function, you can point it to FuncA or FuncB assuming that they have the same signature.
You cannot do what you want to do directly. However, you can achieve a similar result with some slightly different criteria, using something you are already familiar with -- function pointers. Consider:
// This type could be whatever you need, including a member function pointer type.
typedef void (*FunctionPointer)();
struct T {
FunctionPointer Function;
};
Now you can set the Function member on any given T instance, and call it. This is about as close as you can reasonably get, and I presume that since you are already aware of function pointers you're already aware of this solution.
Why don't you edit your question with a more complete description of the problem you're trying to solve? As it stands it really sounds like you're trying to do something horrible.
Its simple!
For
at run time calling funcA() actually results in a call to funcB().
write funcA() similar to following:
int funcA( int a, int b) {
return funcB( a, b );
}
:-)
What is mean by delegates in c++, does sort function in c/c++ which takes a compare function/functor as last parameter is a form of delegate?
"delegate" is not really a part of the C++ terminology. In C# it's something like a glorified function pointer which can store the address of an object as well to invoke member functions. You can certainly write something like this in C++ as a small library feature. Or even more generic: Combine boost::bind<> with boost::function<>.
In C++ we use the term "function object". A function object is anything (including function pointers) that is "callable" via the function call operator().
std::sort takes a "predicate" which is a special function object that doesn't modify its arguments and returns a boolean value.
Callback functions in C++ can be (loosely) referred as a form of delegates ( though delegate term is not used for this). The callback functions use Pointers to Functions to pass them as parameters to other functions.
But delegates in C# is more advanced compared to callback functions in C++.
To delegate work means to share the work load with others. In real life, if you were to delegate your task, ie if you are a manager, you would be sharing your work expecting others to complete a task without you having to know how.
The concept is the same in C++ and any other languages having the capability of delegates. In C you could see this as a delegate:
int calculate(int (*func)(int c), int a, int b)
Because you are expected to send a pointer, to another function which will compute some work for you. I recently wrote a blog post on function pointers in Python and C, check it out, you might find it helpfull. This might not be the "traditional" way to delegate work in C or C++, but then again, the termonoligy says i am a bit right.
Delegation is mostly used as a way to pass functions to functionality embedded in a class (pimpl, aggregation, private inheritance). They are mainly (inlined) functions of one line, calling functions of member-classes. As far as I know, it has nothing to do with C#'s delegates.
In this sense, a function-pointer as used in qsort is not a delegate, but a callback in which framework modules can be extended by user-software as in the Hollywood principle.
Delegate: An object that acts like a multi-function pointer with a subscription system. It really simplifies the use of static or 'object' member function pointers for callback notifications and event handling.
This link explains Delegates in a lucid manner or you may also refer to the MSDN link.