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?
Related
I'm trying to defined an external constructor when porting a class to python, by using make_constructor absolutely fails. When I try:
#include <boost/python/numpy.hpp>
using boost::python;
class foo
{
int i;
public:
foo(int i) : i(i){}
};
foo foo_create(int i){return foo(i);}
BOOST_PYTHON_MODULE(bar)
{
class_<foo>("foo")
.def("__init__", make_constructor(&foo_create));
}
I get the following error
error: no type named ‘element_type’ in ‘class foo’
I tried using noinit and init() with the same result. What am I doing wrong?
Awe found the problem, part of it being the really sparse documentation on make_construction. I needed to return a ptr to a new instance like so (in this case I made them shared pointers):
#include <boost/python/numpy.hpp>
#include <memory>
using boost::python;
class foo
{
int i;
public:
foo(int i) : i(i){}
};
std::shared_ptr<foo> foo_create(int i){return std::shared_ptr<foo>(foo(i));}
BOOST_PYTHON_MODULE(bar)
{
class_<foo, std::shared_ptr<foo>>("foo")
.def("__init__", make_constructor(&foo_create));
}
The documentation on make_constructor is really sparse, but there is some discussion here: https://wiki.python.org/moin/boost.python/HowTo under point "9".
I want to access a variable in multiple .cpp files. I looked into several resources. I could not solve it though. I am using cmake to build all the codes in this project. Following is an example that exactly matches with my problem. Basically, I want val to print 42 in both code1.cpp and code2.cpp. When, I build these three files it complains: undefined reference to 'he::val' collect2: error:ld returned 1 exit status for both the .cpp files.
header1.h
#ifndef HEADER1_H
#define HEADER1_H
#include <iostream>
namespace he {
extern int val;
}
#endif // HEADER1_H
code1.cpp
#include "header1.h"
#include <iostream>
using namespace he;
int func()
{
std::cout << val << std::endl;
}
int main()
{
val=20;
func();
return 0;
}
code2.cpp
#include <iostream>
#include "header1.h"
using namespace he;
int main()
{
std::cout << val << std::endl;
}
extern int val;
Is a variable declaration. You need, somewhere (in one of your cpp files), to define the variable:
int val;
Actually, since you have two main() functions, these are two separate programs. Then your variable definition needs to be in both, like this:
namespace he {
int val;
}
But your extern declaration in the header file makes your variable global, which is usually frowned upon. It all depends, of course on what your purpose is.
Also, since two main() functions mean two separate programs, there is no variable sharing.
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.
I have the following Problem using doxygen in an C project. I have many internal structures that are not documented. Therefore it set EXTRACT_ALL=NO in my Doxyfile. Unfortunately doxygen still extracts some of them. Here is a minimal working example. Suppose the following header file:
#ifndef HASHTABLE_H
# define HASHTABLE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef void* object;
typedef char *(*object_getname)( object obj);
typedef void (*object_free)( object obj);
typedef mess_int_t (*object_hash)( char *name, mess_int_t size);
typedef struct {
hashtable_entry *next;
object *obj;
} hashtable_entry;
typedef struct {
object_getname name;
object_free freigabe;
object_hash hash;
mess_int_t size;
hashtable_entry **hashtable;
} hashtable_t;
typedef hashtable_t * hashtable;
#ifdef __cplusplus
}
#endif
#endif
and the following options set in the Doxyfile:
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
But in the generate Data structure list both structures are listed. Some other undocumented structures defined in the same way in other files are not listed as I expect it from the description of EXTRACT_ALL=NO. Why does doxygen extract some and others not?
The whole doxyfile is available at: http://pastebin.com/J7c9BbvW
I am using doxygen 1.8.5
The answer of the problem is, like we already discussed it in the above comments, that the following setup works:
EXPORT_ALL=NO
in the Doxyfile prevents doxygen only extract data structures from header files instead of all source files.
Setting
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
disables the listing of undocumented structures in the header files.
ENABLE_PREPROCESSING = NO
Unfortunately, doxygen does not parse multi-including header files protect:
#ifndef HASHTABLE_H
# define HASHTABLE_H
I am programming a graph using a list of lists. For that, I have two classes, and each one of this classes has a pointer to another object of the same class and a pointer to the object of the second class. Here is the code:
File V.h:
#ifndef VERTICEPUNT_H
#define VERTICEPUNT_H
#include "A.cpp"
typedef char E;
class V
{
public:
E etiqueta;
V* siguiente;
A* primera; //<- Error: 'A' does not name a type
V();
~V();
};
#endif // VERTICEPUNT_H
File V.cpp:
#include "V.h"
V::V()
{
etiqueta = ' ';
siguiente = 0;
primera = 0; //<- Error: 'primera' was not declared in this scope
}
V::~V()
{
delete primera;
delete siguiente;
}
File A.h:
#ifndef ARISTAPUNT_H
#define ARISTAPUNT_H
#include "V.cpp"
typedef int P;
class A
{
public:
P peso;
V* vertice;
A* siguiente;
A();
~A();
};
#endif // ARISTAPUNT_H
A.cpp:
#include "A.h"
A::A() //<- Error: 'A' does not name a type
{
peso = 0;
siguiente = 0;
vertice = 0;
}
A::~A() // <- Error: 'A' does not name a type
{
delete siguiente;
}
How would I be able to fix that?
The message means that the class name is not in scope. V.h should not include A.cpp, it should include A.h. Same goes for A.h inclusion of V.cpp.
In general, you never want to #include a CPP file - from a header or from another CPP file. Only .h header files are designed for inclusion by preprocessor.
In case of circular definitions like this, you should forward-declare the class the pointer to which you are defining, and forego inclusion of that class's header:
#ifndef VERTICEPUNT_H
#define VERTICEPUNT_H
class A; // <<== Forward declare the class.
typedef char E;
class V
{
public:
E etiqueta;
V* siguiente;
A* primera;
V();
~V();
};
#endif // VERTICEPUNT_H