Strange LLVM warning: no previous prototype for function for - iphone

If I missed the prototype, XCode (LLVM) prompt me for error
no previous prototype for function for exceptionHandler
But why they are needed in my code below?
void exceptionHandler(NSException * exception); // Why this Line is needed?
void exceptionHandler(NSException * exception)
{
// ....
}
#implementation AppDelegate
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
NSSetUncaughtExceptionHandler(&exceptionHandler);
...

From the GCC manual:
-Wmissing-prototypes (C and Objective-C only)
Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is to detect global functions that fail to be declared in header files.
Clang borrowed this option for GCC compatibility, and because it's useful (I would presume this of the Clang devs).
The option exists so you can prevent yourself from making a common mistake which may be easily avoided. It's nice to be explicit about visibility/linkage for clarity/intent's sake.
In short, you've asked the compiler to tell you when an unqualified definition does not match a declaration by enabling this option. You should either qualify that as extern and make it usable to others (e.g. put it in a header), or declare it static. If using C++ inline is also an option.
Of course, implicit visibility is well known, but I typically find the option useful in these scenarios:
1) I made a typo:
// file.h
extern void MONExceptionHandler(NSException * exception);
and
// file.m
void MONExceptionhandler(NSException * exception) {
…
2) I should be explicit about the symbol's visibility:
// file.m
static void MONExceptionHandler(NSException * exception) {
…
3) I forgot to #include the header which declared the function:
// file.h
extern void MONExceptionHandler(NSException * exception);
Warning:
// file.m
void MONExceptionHandler(NSException * exception) {
…
No Warning:
// file.m
#include "file.h"
void MONExceptionHandler(NSException * exception) {
…
So there's the rationale, history, and some examples - again, -Wmissing-prototypes is an option. If you trust yourself to work with it disabled, then do so. My preference is to be explicit, and to let programs detect potential and actual issues so I don't have to do it manually.

If you're declaring a function only for use within this file, prefix the declaration with the static keyword and the warning will go away. As it is, you're declaring a global function; theoretically it could be called from anywhere within your app. But as you've given it no prototype, nobody else could call it.
So the warning, as I understand it, is trying to make you clarify your intentions between static functions and global functions, and discourage you from declaring a global function when you meant to declare only a static one.

I think this is most useful for C++ code. For example I have header
class MyClass {
public:
void hello();
};
and .cpp file
void hello() {
cout << "hello";
}
And you will see the warning because there are no prototype for function void hello(). In case the correct implementation should be
void MyClass::hello() {
cout << "hello";
}
So this warning make sure you are implementing the function that you are aware of (not miss typed a name or different argument format).

That warning is alerting that you can't call your method from another method that is written above. In C, the order of the declaration/implementation minds a lot and gives the difference between something that you can access or you can't.

Related

Doxygen: Force undeclared functions to be documented

Our C++ program has a built-in script interface and is able to run scripts in it. The scripts have access to convenience functions provided by the C++ program.
Now we would like Doxygen to create the documentation of the functions the script has access to. Such a function declaration looks like this:
void ScriptEngine::load_script(const QString &path) {
//...
/*! \fn sleep_ms(const unsigned int timeout_ms)
\brief sleeps for timeout_ms milliseconds.
\param timeout_ms
*/
(*lua)["sleep_ms"] = [](const unsigned int timeout_ms) {
//sleep(timeout_ms)
};
//more convenience functions..
//...
}
Obviously Doxygen won't include a
sleep_ms(const unsigned int timeout_ms)
into the documentation. Is there a way to to tell Doxygen to do so?
Do this:
Add the following line to your Doxyfile:
PREDEFINED = _DOXYGEN_
Make sure the ENABLE_PREPROCESSING tag in the Doxyfile is set to YES.
Put your declarations and documentation for the undeclared functions inside an #ifdef _DOXYGEN_ section.
#ifdef _DOXYGEN_
/*! \fn sleep_ms(const unsigned int timeout_ms)
\brief sleeps for timeout_ms milliseconds.
\param timeout_ms
*/
void sleep_ms(const unsigned int timeout_ms);
#endif
Don't put the above code inside a method or function such as ScriptEngine::load_script(), as you previously tried. And don't put it inside a namespace or class, unless in fact the function being declared is a member of that namespace or class.
With this method, your declarations will not create linker errors during a normal build, but will be seen by Doxygen.
See Also
http://www.doxygen.nl/manual/config.html#cfg_predefined

Using a Function pointer inside a class crashes the compiler (but works inside a function)

Reference class
class commandsListClass
{
public:
std::string name;
std::string description;
std::vector<std::string> commands;
columnHeaders headersRequired;
void (*function)(System::Object ^ );
std::string recoveryFileHeader;
void reset()
{
name = "";
description = "";
commands.clear();
headersRequired.reset();
recoveryFileHeader = "";
function = dummyFunc; // dummyFunc uses the same members as the intended - this is to ensure it is defined. DummyFunc is empty, returns void etc
}
commandsListClass()
{
reset();
}
};
Currently, if I run the below code, the compiler crashes
// This crashes the compiler
System::Threading::ThreadPool::QueueUserWorkItem(gcnew System::Threading::WaitCallback(global::commandsList[index].function ), ti);
1>------ Build started: Project: MyProject, Configuration: Release x64 ------
1> project.cpp
1>c:\users\guy\documents\visual studio 2012\projects\MyProject\MyProject\Form1.h(807): fatal error C1001: An internal error has occurred in the compiler.
1> (compiler file 'msc1.cpp', line 1443)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
If I declare a member inside the same function as I am making the call, and set it to the global::commandsList[index].function, it compiles and runs correctly
// This runs correctly
void (*func)(System::Object ^);
func = global::commandsList[index].function;
System::Threading::ThreadPool::QueueUserWorkItem(gcnew System::Threading::WaitCallback(func ), ti);
global::commandsList is a vector of type commandsListClass
Any ideas? Browsing Google and SO suggest changing the compiler to not optimize, which I've tried with no success. The code is written in such a way that:
That point in the code cannot be reached if index does not point to a valid member of the global::commandsList vector
The function variable is guaranteed to be set, either to the dummyFunc on creation, or the correct (requested) function as set elsewhere in the code.
Any help would be greatly appreciated.
Edit 1: This is using Visual Studio 2012, Windows 7 x64
Here's a simplified repo:
public delegate void MyDel(Object^);
void g(Object^) {}
struct A {
static void(*fs)(Object^);
void(*f)(Object^);
gcroot<MyDel^> del;
};
void(*fg)(Object^);
void h()
{
void (*f)(Object^);
A a;
gcnew MyDel(f);
gcnew MyDel(fg);
gcnew MyDel(a.fs);
a.del = gcnew MyDel(g);
//gcnew MyDel(a.f); // this line fails
// work around
f = a.f;
gcnew MyDel(f);
}
Only the non-static member variable fails. Seems like a compiler bug. Work around it by using a local intermediate.
Or better is Lucas's suggestion to use gcroot.

Call function in main program from a library in Arduino

I've just started making libraries in Arduino. I've made a library named inSerialCmd. I want to call a function named delegate() that is defined in the main program file, stackedcontrol.ino, after the inSerialCmd library is included.
When I try to compile, one error is thrown:
...\Arduino\libraries\inSerialCmd\inSerialCmd.cpp: In member function
'void inSerialCmd::serialListen()':
...\Arduino\libraries\inSerialCmd\inSerialCmd.cpp:32: error:
'delegate' has not been declared
After doing a bit of searching, it seemed that adding the scope resolution operator might do the trick. So I added the "::" before delegate(), now "::delegate()", but the same error is thrown.
Now I'm stumped.
You cannot and should not directly call a function in a program from a library. Keep in mind a key aspect that makes a library into a library:
A library does not depend on the specific application. A library can be fully compiled and packaged into the .a file without the existence of a program.
So there is a one way dependency, a program depends on a library. This at first glance may seem to prevent you from achieving what you want. You can achieve the functionality you are asking about through what is sometimes referred to as a callback. The main program would provide to the library at runtime a pointer to the function to execute.
// in program somwehere
int myDelegate(int a, int b);
// you set this to the library
setDelegate( myDelegate );
You see this in the arduino if you look at how interrupt handlers are installed. This same concept exists in many environments - event listeners, action adapters - all with the same goal of allowing a program to define the specific action that a library cannot know.
The library would store and call the function via the function pointer. Here is a rough sketch of what this looks like:
// in the main program
int someAction(int t1, int t2) {
return 1;
}
/* in library
this is the delegate function pointer
a function that takes two int's and returns an int */
int (*fpAction)(int, int) = 0;
/* in library
this is how an application registers its action */
void setDelegate( int (*fp)(int,int) ) {
fpAction = fp;
}
/* in libary
this is how the library can safely execute the action */
int doAction(int t1, int t2) {
int r;
if( 0 != fpAction ) {
r = (*fpAction)(t1,t2);
}
else {
// some error or default action here
r = 0;
}
return r;
}
/* in program
The main program installs its delegate, likely in setup() */
void setup () {
...
setDelegate(someAction);
...

Duplicate symbol _calculate_string error message iPhone

This is the error code i get when i attempt to build for testing, how do i find the cause for this error. I had duplicted 2 files in xcode and made subtle changes to copy in order to make a second screen.
ld: duplicate symbol _calculate_string in /Users/Lucky3kj/Library/Developer/Xcode /DerivedData/MiniCalculator-ebxkovztnlrphaahncircdyuwjgc/Build/Intermediates/MiniCalculator.build/Debug-iphoneos/PipeFitter.build/Objects-normal/armv7/RollingOffsetLeftViewController.o and /Users/Lucky3kj/Library/Developer/Xcode/DerivedData/MiniCalculator-ebxkovztnlrphaahncircdyuwjgc/Build/Intermediates/MiniCalculator.build/Debug-iphoneos/PipeFitter.build/Objects-normal/armv7/RollingOffsetAnyAngleViewController.o for architecture armv7
Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang failed with exit code 1
Basically, this is an error that stems from C.
If, in one .c file I have the following:
void myFunction(int myArg)
{
printf("%i", myArg);
}
And in another file I have this function:
void myFunction(int myArg)
{
printf("MyArg is: %i", myArg);
}
When the compiler links your project, and you call
myFunction(10);
The compiler does not know which version of your method to call, so the solution is one of the following:
1) Define the method once, and include only the prototype of the function. Example:
// instead of implementing myFunction here, we do this:
void myFunction(int myArg);
// and implement myFunction in another file.
-(void) viewDidLoad {
myFunction(10);
}
2) Define the method twice, but add the static qualifier to it, which tells the linker that this is the only file that can use this function.
// FileOne.c
static void myFunction(int myArg)
{
printf("myArg is: %i", myArg);
}
// FileTwo.c
static void myFunction(int myArg)
{
printf("%i", myArg);
}
Honestly, for simplicity, I would recommend just using the static qualifier, but thats just my preference when It comes to these matters.
This error generally come where you have done a circular reference or making two class files with same name.

Understanding the Objective-C++ __block modifier

I need to do some maintenance on an Objective-C application (updating it to use a new API), and having never used the language before, I'm a bit confused.
I have an Objective-C++ class which implements an interface from my API, and this is used within a block, however whenever it is accessed within the block, it fails with an access violation error (EXC_BAD_ACCESS).
Furthrer investigation shows that none of the constructors for the object in question are being called. It is declared within the containing scope, and uses the __block modifier.
To try and understand this, I made a quick scratch application, and found the same thing happens there:
class Foo
{
public:
Foo() : value(1) { printf("constructor"); }
void addOne() { ++value; printf("value is %d", value); }
private:
int value;
};
void Bar()
{
Foo foo1; // prints "constructor"
__block Foo foo2; // doesn't print anything
foo1.addOne(); //prints "2"
foo2.addOne(); //prints "1"
}
Can anyone explain what is happening here? Why isn't my default constructor being called, and how can I access the object if it hasn't been properly constructed?
As I understand it, your example there isn't using a block as such, but is declaring foo2 as to be used by a block.
This does funny things to the handling of foo2, which you can read more about here.
Hope that helps.
Stumbled upon this old question. This was a bug that's long been fixed. Now __block C++ objects are properly constructed. If referenced in a block and the block is copied, the heap copy is move-constructed from the original, or copy-constructed if it cannot be move-constructed.