I am working on a proprietary tool which uses a C++-like language to define various methods. The tool provides its own compiler to compile these methods into a .so file. It does not follow the "declaration-definition" syntax of C++, but is otherwise quite similar. An example code looks like the following:
method _foo::bar(var message) {
// do something with 'message' here
}
I tried documenting this method using doxygen as follows:
/**
* #brief this method does something with #a message.
*/
method _foo::bar(var message) {
// do something with 'message' here
}
but this gave me a warning:
warning: documented function `method _foo::bar' was not declared or defined.
I tried with adding #fn method _foo::bar(), #fn _foo::bar, and #fn bar to the comment block (one by one), but neither of them resulted in the #brief message being added to the document.
I have searched here on Stack Overflow, and this post Doxygen comments with undeclared functions in C++ headers is the closest to my question, but it doesn't quite address my problem.
Is there any way to configure doxygen to generate documentation for a function regardless of the fact that it is undeclared?
Related
I am trying to use Doxygen to document some C++ code that uses Microsoft's Source-Code Annotation Language (SAL). However, Doxygen does not parse certain annotation macros, like _Success_, correctly. In the case of the example function annotation, _Success_, Doxygen misinterprets this macro as the function header/prototype.
Take the following example that contains the function annotation marker:
/**
* #file
* Example with function annotation.
*/
#include <windows.h>
#include <sal.h>
/**
* #brief This is a function.
* #param i a random variable
* #return TRUE on every call.
*/
_Success_(return) // The SAL function annotation.
BOOL function(_In_ int i) {
return TRUE;
}
With the example above, Doxygen will interpret _Success_() as the function header/prototype and thereby, creates documentation that is absolutely wrong. Here is what the HTML Doxygen output appears like with and without the function annotation:
With the function annotation, Doxygen also says I have documented a parameter variable i that is not part of the list of arguments:
C:/.../Source.cpp:9: warning: argument 'i' of command #param is not found in the argument list of Success(return)
Am I missing a configuration setting in the main Doxygen configuration file?
Or is SAL and Doxygen simply just incompatible?
Ah ha! After some further research, I found a question on Stack Overflow that asked this same question, except it wasn't tagged correctly and did not explicitly say s/he was using "Microsoft's SAL." This is why it took me awhile to find it. (I have updated the corresponding question to correct these missteps.)
The question's answer references the Doxygen manual section entitled: Preprocessing.
A typically example where some help from the preprocessor is needed is when dealing with the language extension from Microsoft: __declspec. The same goes for GNU's __attribute__ extension. [...] When nothing is done, doxygen will be confused and see __declspec as some sort of function. [...]
Therefore, as pertaining to my example above, the settings that need to be configured in the Doxygen configuration file are as follows:
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = _Success_(x)= \
_In_=
Basically, this set of configurations means that the macros defined in the PREDEFINED section will be fully expanded and evaluated "before the preprocessor [has] started." But, these macros will expand to nothing as we provide "nothing" for the definition side of the equation (i.e. format: name=definition). Therefore, they are essentially ignored/removed while Doxygen builds the documentation documents.
Unfortunately, this does mean that one will need to continue to expand this PREDEFINED list to encapsulate, at least, all the SAL macros used in the source code. A better solution would to encapsulate all the SAL macros in this list, but future proofing is impossible as one will always be late at appending any new macros that are added later on. But, at least, there is a solution!
I am studying Import Export Extension of Khronos openvx. while reading vx_import.h file I saw
VX_API_ENTRY vx_status VX_API_CALL vxReleaseImport(vx_import *import);
function.
I want to understand why they have written VX_API_ENTRY and VX_API_CALL in the function.
I am new to openvx. If anyone knows this please reply.
In the vx_types.h header you can read:
/*!
* \internal
* \def VX_API_ENTRY
* \brief This is a tag used to identify exported, public API functions as
* distinct from internal functions, helpers, and other non-public interfaces.
* It can optionally be defined in the make system according the the compiler and intent.
* \ingroup group_basic_features
*/
/*!
* \def VX_API_CALL
* \brief Defines calling convention for OpenVX API.
* \ingroup group_basic_features
*/
/*!
* \def VX_CALLBACK
* \brief Defines calling convention for user callbacks.
* \ingroup group_basic_features
*/
Then, VX_API_ENTRY is defined as empty and VX_API_CALL is defined __stdcall on Windows, and empty otherwise.
What are they for? Well, those are specifying the calling convention of the API, and at the same time, as the comment says, documenting which functions are actually public.
For example, in Windows, public functions from a DLL sometimes have declspec(__dllimport) prefixed to instruct the compiler to use the import function table, your build system can define VX_API_ENTRY for that.
The __stdcall thing is the calling convention used by this library. Usually you do not specify it and let the compiler choose the default. But in a public DLL it is a good idea not to rely to much on defaults, because the DLL compiler and the EXE compiler may use different values, and that would break the linking.
But mostly, as an end-user of the API you can just ignore them, they just work.
Except for VX_CALLBACK! You must declare your callbacks as VX_CALLBACK or you risk your code failing on some architectures (mainly Windows).
I need to parse a C++ class file (.h) and extract the following informations:
Function names
Return types
List of parameter types of each function
Assume that there is a special tag using which I can recognize if I need to parse a function or not.
For eg.
#include <someHeader>
class Test
{
public:
Test();
void fun1();
// *Expose* //
void fun2();
};
So I need to parse only fun2().
I read the basic grammar here, but found it too complex to comprehend.
Q1. I can't make out how complex this task is. Can someone provide a simpler grammar for a function declaration to perform this parsing?
Q2. Is my approach right or should I consider using some library rather than reinventing?
Edit: Just to clarify, I don't have problem parsing, problem is more of understanding the grammar I need to parse.
A C++ header may include arbitrary C++ code. Hence, parsing the header might be as hard as parsing all kinds of C++ code.
Your task becomes easier, if you can make certain assumptions about your header file. For instance, if you always have an EXPOSE-tag in front of your function and the functions are always on a single line, you could first grep for those lines:
grep -A1 EXPOSE <files>
And then you could apply a regular expression to filter out the information you need.
Nevertheless, I'd recommend using existing tools. This seems to be a tutorial on how to do it with clang and Python.
GCC XML is an open source tool that emits the AST (Abstract Syntax Tree). See this other answer where I posted about the usage I made of it.
You should consider to use only if you are proficient (or akin to learn) with an XML analyzer for inspecting the AST. It's a fairly complex structure...
You will need anyway to 'grep' for the comments identifying your required snippets, as comments are lost in output XML.
IF you are doing this just for documentation doxygen could be a good bet.
Either way it may give you some pointers as to how to do this.
I have a vendor specifc code for ADC and other peripherals.
Now using it I am understanding the flow.
the extension of the files are .cpp but the statements there are similar to C rather C++
i.e. printf() is used instead of cout;
no namespace.std defined... also other things which made me sure that it is a c-language code.
(pardon me but whatever I ask the vendors but response is quite late from there)
So it is a complete C- code. But while understangin I came to a point where the class is defined and I am really puzzled now. Since I have not seen or heard any one using class
C4DSPBlast cBlast;
cBlast.GetBlastInfo();
where C4DSPBlast cBlast;
and following code shows that C4DSPBlast is a class. Now, while debugging, I found that I am getting error at exactly this statement cBlast.GetBlastInfo();
but since I don't know the classes in C- I post it here since I am not getting any forward any further in debugging.
class C4DSPBlast
{
public:
//! empty constructor.
C4DSPBlast(void);
//! empty destructor.
~C4DSPBlast(void);
//! Get BLAST information from the hardware(firmware).
/*!
* Read the BLAST information from an the PCI memory attached to the hardware device. This function populates internal class members with this information.
* #return CBLAST_IO_ERROR_BLAST_INFO_RD, CBLAST_NO_DEV_TYPE or CBLAST_SUCCESS if no errors.
*/
int GetBlastInfo(void);
//! m_valBLASTRegister the standard BLAST information register.
union { BLASTReg m_BLASTRegister; unsigned long m_val0; } m_valBLASTRegister;
//! m_valBLASTRegisterExt the extended BLAST information register.
union { BLASTReg m_BLASTRegisterExt; unsigned long m_val1; } m_valBLASTRegisterExt;
//! The whole BLAST information populated by GetBlastInfo() as a C data structure.
struct BOARD m_cBoard;
};
The code is C++. Compile it as C++ and the errors will disappear.
C and C++ are different languages. Current common convention is that if you give file with an extension .c to the compiler, it will compile it as C file. If you give it a .cpp or .cxx (exact list depends on the compiler) it will process it as C++ file. This will work even if you put mixture of C/C++ files on the same command line.
If you pick up arbitrary C file, rename to .cpp, and give it to compiler, 99% chance that it will be compiled. C++ standard describes a list of incompatibilities with C, but these are rather rare things.
Most likely that you see a file that was created as C and then started its new life as C++.
I have been thinking about this for really long time (in fact, years) and searching best way to handle exceptions in C++. And so I thought of tool, which could help me and so I would like to ask if this tool exists (I couldn't Google it).
This tool would parse C++ source code (both headers and sources) and filled doxygen-like comments with exception info (preferably extending comments I already wrote about method itself). For each method exception list would be generated from code - from each time there is "throw SomeException;" command, from list of called functions (beware of recursion) and from known commands possible throwing exceptions (currently, I can fink only of operator new). So I could track all exceptions and see if I forget to manage exception from other modules and see if there is accidental possibility of throwing exception from destructor (which prohibited AFAIK).
Or I could use similar tool which wouldn't automatically fill doxygen comments, but at least warn me about not commented ones. Similarly like when I run doxygen documentation generator, I forget comment one input variable and the generator warns me about this.
So, is there such tool? And if not, is there very simple-to-use library parsing C++ code so I could easily implement it for myself?
Example:
//// Example.h ////
/**
* Does almost nothing.
*/
void foo1();
/**
* Generates some error.
*/
void foo2();
//// Example.cpp ////
#include "Example.h"
void foo1()
{
foo2();
}
void foo2()
{
throw MyException();
}
This would:
Add "#throw MyException" line to foo1() comment.
Give warning: "foo1() in file ... line ...: throws MyException, but not in comment!"
I know that C++ language provides possibility of specification of possibly thrown exceptions, problem is that this is not checked in compile time, but in runtime. And I need to handle this case (std::unexpected if I remember correctly).
It's not problem if this tool is needed to be run manually, like doxygen, and not at every time I compile.