One of Objective C's primary features is simple introspection. A typical use of this functionality is the ability to check some method (function), to make sure it indeed exists, before calling it.
Whereas the following code will throw an error at runtime (although it compiles just fine (Apple LLVM version 7.0.2 (clang-700.1.81)))...
@import Foundation;
@interface Maybe : NSObject + (void) maybeNot; @end
@implementation Maybe @end
int main (){ [Maybe maybeNot]; }
By adding one simple condition before the call...
if ([Maybe respondsToSelector:@selector(maybeNot)])
We can wait till runtime to decide whether or not to call the method.
Is there any way to do this with "standard" C (c11) or C++ (std=c14)?
i.e....
extern void callMeIfYouDare();
int main() { /* if (...) */ callMeIfYouDare(); }
I guess I should also mention that I am testing/using this is in a Darwin runtime environment.
On GNU gcc / Mingw32 / Cygwin you can use Weak symbol:
#include <stdio.h>
extern void __attribute__((weak)) callMeIfYouDare();
void (*callMePtr)() = &callMeIfYouDare;
int main() {
if (callMePtr) {
printf("Calling...\n");
callMePtr();
} else {
printf("callMeIfYouDare() unresolved\n");
}
}
Compile and run:
$ g++ test_undef.cpp -o test_undef.exe
$ ./test_undef.exe
callMeIfYouDare() unresolved
If you link it with library that defines callMeIfYouDare though it will call it. Note that going via the pointer is necessary in Mingw32/Cygwin at least. Placing a direct call callMeIfYouDare() will result in a truncated relocation by default which unless you want to play with linker scripts is unavoidable.
Using Visual Studio, you might be able to get __declspec(selectany) to do the same trick: GCC style weak linking in Visual Studio?
Update #1: For XCode you can use __attribute__((weak_import)) instead according to: Frameworks and Weak Linking
Update #2: For XCode based on "Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)" I managed to resolve the issue by compiling with the following command:
g++ test_undef.cpp -undefined dynamic_lookup -o test_undef
and leaving __attribute__((weak)) as it is for the other platforms.
If you can see a function of an object (not pointer) is called in a source code and the code is compiled successfully - then the function does exist and no checking needed.
If a function being called via a pointer then you assume your pointer is of type of the class that has that function. To check whether it's so or not you use casting:
auto* p = dynamic_cast<YourClass*>(somepointer);
if (p != nullptr)
p->execute();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With