Reputation: 16473
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.
Upvotes: 3
Views: 1363
Reputation: 654
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.
Upvotes: 5
Reputation: 1
C++ or C don't have introspection. You could add some with your additional layer (look at Qt metaobject, or GTK GObject introspection for examples); you might consider customizing GCC with MELT to get some introspection... (but that would take weeks). You could have some additional script or tool which emits C or C++ code related to your introspection needs (SWIG could be inspirational).
In your particular case, you might want to use weak symbols (at least on Linux). Perhaps use the relevant function attribute so code.
extern void perhapshere(void) __attribute__((weak));
if (perhapshere)
perhapshere();
and you might even make that shorter with some macro.
Maybe you just want to load some plugin with dlopen(3) and use dlsym(3) to find symbols in it (or even in the whole program which you would link with -rdynamic
, by giving the NULL
path to dlopen
and using dlsym
on the obtained handle); be aware that C++ uses name mangling.
So you might try
void*mainhdl = dlopen(NULL, RTLD_NOW);
if (!mainhdl) { fprintf(stderr, "dlopen failed %s\n", dlerror());
exit(EXIT_FAILURE); };
then later:
typedef void voidvoidsig_t (void); // the signature of perhapshere
void* ad = dlsym(mainhdl, "perhapshere");
if (ad != NULL) {
voidvoidsig_t* funptr = (voidvoidsig_t*)ad;
(*funptr)();
}
Upvotes: 1
Reputation: 673
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();
Upvotes: 1