I have a function called init in a cpp file, but when I compile it, g++ creates in the object file a symbol named _Z4initv, so when I link after with ld with the option -e init, obviously ld doesn't recognize the symbol init. Is there a way to create symbols name in C style with g++ ?
If you have a definition like e.g.
void init() { ... /* some code */ ... }
Then to inhibit name mangling you need to declare it as extern "C":
extern "C" void init() { ... /* some code */ ... }
If you have a declaration in a header file that you want to include in a C source file you need to check if you're including the header file in a C or C++ source file, using the __cplusplus macro:
#ifdef __cplusplus
extern "C"
#endif
void init(void);
Note that the function in the header file has to be declared with void in the argument list, if it doesn't take any arguments. That's because the declaration void init() means something else in C.
Related
Short version
To prevent the compiler from raising a warning about unused variables I define the macro UNUSED as:
UNUSED(x)=x __attribute__((__unused__))
This macro is then employed in some functions' prototypes, for instance :
void ext(int foo, int UNUSED( bar ) )
However, doxygen is unhappy about that and returns some warnings:
/tmp/sandbox/main.cpp:13: warning: argument 'bar' of command #param is not found in the argument list of Dummy::ext(int foo, intUNUSEDbar)
/tmp/sandbox/main.cpp:13: warning: The following parameters of Dummy::ext(int foo, intUNUSEDbar) are not documented:
parameter 'UNUSED'
How should I tell doxygen to ignore the UNUSED macro ?
Long version
I have a code that looks like the following :
#include <iostream>
class Dummy
//! Dummy class
{
public :
//!Dummy function
/**
* \param foo First variable
* \param bar Second variable
*/
void ext(int foo, int UNUSED( bar ) )
{
std::cout << "foo = " << foo << std::endl;
}
};
//!Main function
int main(void)
{
Dummy MyDummy;
MyDummy.ext(1, 2);
return 0;
}
I compile it by invoking :
g++ -D 'UNUSED(x)=x __attribute__((__unused__))' main.cpp
To generate the default doxygen configuration file named Doxyfile I enter :
doxygen -g
Eventually, to generate the documentation I enter :
doxygen Doxyfile
The latter command outputs the following warning :
/tmp/sandbox/main.cpp:13: warning: argument 'bar' of command #param is not found in the argument list of Dummy::ext(int foo, intUNUSEDbar)
/tmp/sandbox/main.cpp:13: warning: The following parameters of Dummy::ext(int foo, intUNUSEDbar) are not documented:
parameter 'UNUSED'
Following instructions from the doxygen documentation, modify the Doxyfile so that it has the following parameters :
#Doxygen will run its own preprocessor before parsing the file
ENABLE_PREPROCESSING = YES
#The Doxygen preprocessor will not only define the macros (default
#behaviour) but also expand them
MACRO_EXPANSION = YES
#The Doxygen preprocessor will only expand the macros that are listed in
#the PREDEFINED setting. Any other macro will merely be defined, and not
#expanded.
EXPAND_ONLY_PREDEF = YES
#The Doxygen preprocessor will replace any occurrence of the UNUSED
#macro by its argument
PREDEFINED = UNUSED(x)=x
After those changes, invoking doxygen Doxyfile no longer raises warnings.
I am missing the
<references>
tags for global variables if the functions using them are defined in the same source file. They are there if I define the global variable in a different source file. Is there any known solution to this? The code is C for an embedded system.
Update:
I have narrowed it down to this: If the function references a member of the global struct, there will be only a reference to the typedef member, not a reference to the variable:
test.h
typedef struct
{
int b;
} a_S;
extern a_S a;
test1.c
#include "test.h"
a_S a;
void UseA1(void)
{
a_S *ptrA = &a; /* working, "UseA1" will reference "a" in the doxygen xml output */
}
void UseA2(void)
{
a.b = 0; /* not working, "UseA2" will NOT reference "a" in the doxygen xml output */
}
But only if the variable is defined in the same source file. If it is defined in another source file, there will be the reference to the variable as well as the reference to the typedef member:
test_data.c
#include "test.h"
a_S a;
test2.c
#include "test.h"
void UseA1(void)
{
a_S *ptrA = &a; /* still working */
}
void UseA2(void)
{
a.b = 0; /* working too! */
}
Unfortunately this is not an option because of our existing coding standards... Is there any way around this?
The question pretty much says it all- how could I import file2.vala to file1.vala?
You don't do it directly. If you run valac file1.vala file2.vala, it is as if you compiled them in one big file.
If you want to make them reusable, then you probably want a shared library. In which case, you compile one to produce a C header file and a VAPI definition:
valac --vapi file1.vapi -H file1.h --library libfile1.so file1.vala
The second one can then consume this:
valac --pkg file1 file2.vala
This assume that the VAPI file has been installed. If this is not the case, you'll need to pass --vapidir and the location where file1.vapi exists, probably .. Similarly, you'll need to inform the C compiler about where file1.h lives with -X -I/directory/containing, again, probably -X -I.. Finally, you'll need to tell the C linker where libfile1.so is via -X -L/directory/containing -X -lfile1. This is a little platform specific, and you can smooth the difference out using AutoMake, though this is a bit more involved. Ragel is the usual go-to project for how to use AutoMake with Vala.
just to supply apmasell:
you can use multiple files by using classes and public variables:
main.vala:
extern void cfunction(string text);
void main ()
{
first f = new first ();
f.say_something(f.mytext);
cfunction("c text\n");
}
class.vala:
public class first {
public string mytext = "yolo\n";
public first ()
{
stdout.printf("text from constructer in first\n");
}
public void say_something(string text)
{
stdout.printf("%s\n", text);
}
}
text.c:
#include <stdio.h>
void cfunction(const char *s)
{
puts("This is C code");
printf("%s\n", s);
}
compiles with: valac class.vala main.vala text.c
as you can see, you can even use C code
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.
I'm using Eclipse and MinGW. I've got undefined reference to error to all that I write in h files, that I do include in cpp-file where main located. I create an empty project, and the same thing again (
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(){
Stack<int> stack(10);
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
stack.h
#ifndef STACK_H_
#define STACK_H_
template <class T>
class Stack{
private:
struct StackEl;
StackEl *top;
public:
Stack();
Stack(T el);
~Stack();
void Push(const T& el);
T Pop();
};
#endif /* STACK_H_ */
and stack.cpp inplements everything from stack.h
If I include not h-file, but cpp - all works. Help please!
I've got following errors
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:16: undefined reference to `Stack<int>::Stack(int)'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
This is a linker error. I'm no Eclipse expert, but you have to tell it somehow to add Stack.o to the linking command.
If you include Stack.cpp instead of Stack.h, the implementations from the cpp-file get included into main.cpp by the preprocessor before compilation, so the linking stage has no unresolved references to outside functions.
My bad, that is becouse templates! When you use template, all code, including realization of functions, must be in header-file, or you have to write prototypes for every type you are going to use you template-functions with. I've forgot about that working with templates is not the same as with usual function :(