No documentation is generated for any of the functions for my C repo
My configuration:
# Difference with default Doxyfile 1.9.1
PROJECT_NAME = WLib
OUTPUT_DIRECTORY = doxy
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_ALL = YES
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = YES
INPUT = .
FILE_PATTERNS = *.c \
*.h
RECURSIVE = YES
Edit the code:
/** \fn Array Fill
* \param sa size of the array A in bytes
* \param a the array A
* \param sb size of the array B in bytes
* \param b the array B
* \brief Takes two arrays and their sizes. Fills the array A with as many
* instances of array B as the size of array A can handle.
* \return The array A
* Method:
* -# If /e a = NULL, then the array of size /e sa will be allocated
* -# If /e b = NULL and /e sb = 0, then array will be filled with zeros
* -# If /e sb = 0, the function does nothing and returns NULL
* -# Declares a variable /e i, this is be the pointer offset
* -# Assignes array /e b to array /e a offsetted by /e i, and incriments
* /e i by /e sb. This step is repeated until less than sb bytes are
* left untreated
* -# Assignes the remaining part of array /e a with whatever piece of
* array /e b fits
*/
VO* afl(register const U16 sa,
register VO* a,
register U8 sb,
register const VO* b ) {
...
}
The supplied code gives directly an answer when running it, it gives the warning:
warning: documented symbol 'Array Fill' was not declared or defined.
when looking at the code we see here:
\fn Array Fill
but from the documentation we learn:
\fn (function declaration)
Indicates that a comment block contains documentation for a function
(either global or as a member of a class). This command is only needed
if a comment block is not placed in front (or behind) the function
declaration or definition.
If your comment block is in front of the function declaration or
definition this command can (and to avoid redundancy should) be
omitted.
A full function declaration including arguments should be specified
after the \fn command on a single line, since the argument ends at the
end of the line!
and furthermore in the given example in the documentaion:
const char *member(char,int) throw(std::out_of_range);
and
/*! \fn const char *Fn_Test::member(char c,int n)
* \brief A member function.
* \param c a character.
* \param n an integer.
* \exception std::out_of_range parameter is out of range.
* \return a character pointer.
*/
in other words the syntax for the \fn command should be in this case:
\fn VO* afl(register const U16 sa, register VO* a, register U8 sb, register const VO* b)
Note:
the \fn command is typically for the usage when the documentation of a function is not directly in font of the function. In the case of the issue the \fn command is not necessary.
It looks like that the \fn here is used in the context of the \brief command and the used \brief command in the context of the \details command.
Related
In my .h file of my C program I have a function:
/** Calculates foo using algorithm A1.
* \param[in] v1 first input
* \param[in] v2 second input
* \param[in] s1 first string
* \param[in] s2 second string
* \return foo(v1,v2)
*/
int foo( int v1, int v2, char *s1, char *s2);
Now in the beginning of the file I want to discuss the function. So I say:
/** To facilitate such operations I have:
* #li int foo( int v1, int v2, char *s1, char *s2)
*
* which allows me to blah.
*/
Now in my doxygen file, the word foo is not linked to the function definition section at the end. However, if I say:
/** To facilitate such operations I have:
* #li int foo()
*
* which allows me to blah.
*/
The autolinking works fine. Including the arguments breaks the autolinking function and I can't for the life of me figure out why. This happens to all my functions which have > 1 input arguments. foo() and foo(int i) work but foo(int i, int j, int k, int m) does not work. Does anyone have any idea why this occurs?
I am trying to document a packed type with Doxygen but I can't figure it out : I don't have the description of each item, do you have an idea of how can I do this ? In the final output, I just have my #brief & detailled description..
/**
* #typedef Pack
*
* #brief Description
* Detailled description
*
*/
typedef enum
__packed
{
A = 0, //!< Description 1
B = 1, //!< Description 2
C = 2 //!< Description 3
}Pack, *PPack;
Thanks for your help !
The comment of #albert is correct but probably a bit short.
For your comfort I state the information form the Doxygen manual that Albert refers to.
To make doxygen understand the __packed keyword you have to adjust your doxygen configuration file like this:
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = __packed
Here you find more information: http://www.doxygen.nl/manual/preprocessing.html
I'm playing around integrating differential forms in maxima, and this is my program:
init_cartan([x,y]);
omega:1/(sqrt(x-y))*dx~dy;
phi:[u^2+v^2,2*u*v];
diff(phi,u);
diff(phi,v);
scalar:diff(phi,v)|(diff(phi,u)|omega);
integrand:subst(u^2+v^2,x,subst(2*u*v,y,scalar));
integrand:radcan(integrand);
integrate(integrate(integrand,u,0,1),v,0,1);
In the subst bit I have to give the relations between u,v and x,y again. This seems redundant. Is there a more natural expression?
Consider this two examples:
load("cartan");
init_cartan([x,y]);
omega:1/(sqrt(x-y))*dx~dy;
/* declare functional dependencies ... */
depends([x, y], [u, v]);
/* this definition can be used latter */
def_xy: [x=u^2+v^2, y=2*u*v];
phi: [x, y];
scalar: diff(phi,v)|(diff(phi,u)|omega);
/* substitute ... */
scalar: subst(def_xy, scalar);
/* and force re-evalution of 'diff */
scalar: ev(scalar, diff);
integrand:radcan(scalar);
integrate(integrate(integrand,u,0,1),v,0,1);
and
load("cartan");
init_cartan([x,y]);
omega:1/(sqrt(x-y))*dx~dy;
/* declare functional dependencies ... */
depends([x, y], [u, v]);
/* give "numeric values" */
numerval(x, u^2+v^2, y, 2*u*v);
phi: [x, y];
scalar: diff(phi,v)|(diff(phi,u)|omega);
/* evaluate to numeric values (also switches `float' to true so 1/2 evaluates to 0.5) ... */
scalar: ev(scalar, numer=true);
/* and force re-evalution of 'diff */
scalar: ev(scalar, diff);
integrand:radcan(scalar);
integrate(integrate(integrand,u,0,1),v,0,1);
load(cartan);
init_cartan([x,y]);
omega:1/sqrt(x-y)*dx~dy;
def_xy:[x=u^2+v^2,y=2*u*v];
phi:subst(def_xy,[x,y]);
scalar:subst(def_xy,(diff(phi,u)|(diff(phi,v)|omega)));
integrand:radcan(scalar);
integrate(integrate(integrand,v,0,u),u,0,1);
I have found a really tricky problem, which I can not seem to fix easily. In short, I would like to return from a mex file an array, which has been passed as mex function input. You could trivially do this:
void mexFunction(int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin[])
{
pargout[0] = pargin[0];
}
But this is not what I need. I would like to get the raw pointer from pargin[0], process it internally, and return a freshly created mex array by setting the corresponding data pointer. Like that:
#include <mex.h>
void mexFunction(int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin[])
{
mxArray *outp;
double *data;
int m, n;
/* get input array */
data = mxGetData(pargin[0]);
m = mxGetM(pargin[0]);
n = mxGetN(pargin[0]);
/* copy pointer to output array */
outp = mxCreateNumericMatrix(0,0,mxDOUBLE_CLASS,mxREAL);
mxSetM(outp, m);
mxSetN(outp, n);
mxSetData(outp, data);
/* segfaults with or without the below line */
mexMakeMemoryPersistent(data);
pargout[0] = outp;
}
It doesn't work. I get a segfault, if not immediately, then after a few calls. I believe nothing is said about such scenario in the documentation. The only requirement is hat the data pointer has been allocated using mxCalloc, which it obviously has. Hence, I would assume this code is legal.
I need to do this, because I am parsing a complicated MATLAB structure into my internal C data structures. I process the data, some of the data gets re-allocated, some doesn't. I would like to transparently return the output structure, without thinking when I have to simply copy an mxArray (first code snippet), and when I actually have to create it.
Please help!
EDIT
After further looking and discussing with Amro, it seems that even my first code snippet is unsupported and can cause MATLAB crashes in certain situations, e.g., when passing structure fields or cell elements to such mex function:
>> a.field = [1 2 3];
>> b = pargin_to_pargout(a.field); % ok - works and assigns [1 2 3] to b
>> pargin_to_pargout(a.field); % bad - segfault
It seems I will have to go down the 'undocumented MATLAB' road and use mxCreateSharedDataCopy and mxUnshareArray.
You should use mxDuplicateArray, thats the documented way:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
plhs[0] = mxDuplicateArray(prhs[0]);
}
While undocumented, the MEX API function mxCreateSharedDataCopy iswas given as a solution by MathWorks, now apparently disavowed, for creating a shared-data copy of an mxArray. MathWorks even provides an example in their solution, mxsharedcopy.c.
As described in that removed MathWorks Solution (1-6NU359), the function can be used to clone the mxArray header. However, the difference between doing plhs[0] = prhs[0]; and plhs[0] = mxCreateSharedDataCopy(prhs[0]); is that the first version just copies the mxArray* (a pointer) and hence does not create a new mxArray container (at least not until the mexFunction returns and MATLAB works it's magic), which would increment the data's reference count in both mxArrays.
Why might this be a problem? If you use plhs[0] = prhs[0]; and make no further modification to plhs[0] before returning from mexFunction, all is well and you will have a shared data copy thanks to MATLAB. However, if after the above assignment you modify plhs[0] in the MEX function, the change be seen in prhs[0] as well since it refers to the same data buffer. On the other hand, when explicitly generating a shared copy (with mxCreateSharedDataCopy) there are two different mxArray objects and a change to one array's data will trigger a copy operation resulting in two completely independent arrays. Also, direct assignment can cause segmentation faults in some cases.
Modified MathWorks Example
Start with an example using a modified mxsharedcopy.c from the MathWorks solution referenced above. The first important step is to provide the prototype for the mxCreateSharedDataCopy function:
/* Add this declaration because it does not exist in the "mex.h" header */
extern mxArray *mxCreateSharedDataCopy(const mxArray *pr);
As the comment states, this is not in mex.h, so you have to declare this yourself.
The next part of the mxsharedcopy.c creates new mxArrays in the following ways:
A deep copy via mxDuplicateArray:
copy1 = mxDuplicateArray(prhs[0]);
A shared copy via mxCreateSharedDataCopy:
copy2 = mxCreateSharedDataCopy(copy1);
Direct copy of the mxArray*, added by me:
copy0 = prhs[0]; // OK, but don't modify copy0 inside mexFunction!
Then it prints the address of the data buffer (pr) for each mxArray and their first values. Here is the output of the modified mxsharedcopy(x) for x=ones(1e3);:
prhs[0] = 72145590, mxGetPr = 18F90060, value = 1.000000
copy0 = 72145590, mxGetPr = 18F90060, value = 1.000000
copy1 = 721BF120, mxGetPr = 19740060, value = 1.000000
copy2 = 721BD4B0, mxGetPr = 19740060, value = 1.000000
What happened:
As expected, comparing prhs[0] and copy0 we have not created anything new except another pointer to the same mxArray.
Comparing prhs[0] and copy1, notice that mxDuplicateArray created a new mxArray at address 721BF120, and copied the data into a new buffer at 19740060.
copy2 has a different address (mxArray*) from copy1, meaning it is also a different mxArray not just the same one pointed to by different variables, but they both share the same data at address 19740060.
The question reduces to: Is it safe to return in plhs[0] either of copy0 or copy2 (from simple pointer copy or mxCreateSharedDataCopy, respectively) or is it necessary to use mxDuplicateArray, which actually copies the data? We can show that mxCreateSharedDataCopy would work by destroying copy1 and verifying that copy2 is still valid:
mxDestroyArray(copy1);
copy2val0 = *mxGetPr(copy2); % no crash!
Applying Shared-Data Copy to Input
Back to the question. Take this a step further than the MathWorks example and return a share-data copy of the input. Just do:
if (nlhs>0) plhs[0] = mxCreateSharedDataCopy(prhs[0]);
Hold your breath!
>> format debug
>> x=ones(1,2)
x =
Structure address = 9aff820 % mxArray*
m = 1
n = 2
pr = 2bcc8500 % double*
pi = 0
1 1
>> xDup = mxsharedcopy(x)
xDup =
Structure address = 9afe2b0 % mxArray* (different)
m = 1
n = 2
pr = 2bcc8500 % double* (same)
pi = 0
1 1
>> clear x
>> xDup % hold your breath!
xDup =
Structure address = 9afe2b0
m = 1
n = 2
pr = 2bcc8500 % double* (still same!)
pi = 0
1 1
Now for a temporary input (without format debug):
>> tempDup = mxsharedcopy(2*ones(1e3));
>> tempDup(1)
ans =
2
Interestingly, if I test without mxCreateSharedDataCopy (i.e. with just plhs[0] = prhs[0];), MATLAB doesn't crash but the output variable never materializes:
>> tempDup = mxsharedcopy(2*ones(1e3)) % no semi-colon
>> whos tempDup
>> tempDup(1)
Undefined function 'tempDup' for input arguments of type 'double'.
R2013b, Windows, 64-bit.
mxsharedcopy.cpp (modified C++ version):
#include "mex.h"
/* Add this declaration because it does not exist in the "mex.h" header */
extern "C" mxArray *mxCreateSharedDataCopy(const mxArray *pr);
bool mxUnshareArray(const mxArray *pr, const bool noDeepCopy); // true if not successful
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
mxArray *copy1(NULL), *copy2(NULL), *copy0(NULL);
//(void) plhs; /* Unused parameter */
/* Check for proper number of input and output arguments */
if (nrhs != 1)
mexErrMsgTxt("One input argument required.");
if (nlhs > 1)
mexErrMsgTxt("Too many output arguments.");
copy0 = const_cast<mxArray*>(prhs[0]); // ADDED
/* First make a regular deep copy of the input array */
copy1 = mxDuplicateArray(prhs[0]);
/* Then make a shared copy of the new array */
copy2 = mxCreateSharedDataCopy(copy1);
/* Print some information about the arrays */
// mexPrintf("Created shared data copy, and regular deep copy\n");
mexPrintf("prhs[0] = %X, mxGetPr = %X, value = %lf\n",prhs[0],mxGetPr(prhs[0]),*mxGetPr(prhs[0]));
mexPrintf("copy0 = %X, mxGetPr = %X, value = %lf\n",copy0,mxGetPr(copy0),*mxGetPr(copy0));
mexPrintf("copy1 = %X, mxGetPr = %X, value = %lf\n",copy1,mxGetPr(copy1),*mxGetPr(copy1));
mexPrintf("copy2 = %X, mxGetPr = %X, value = %lf\n",copy2,mxGetPr(copy2),*mxGetPr(copy2));
/* TEST: Destroy the first copy */
//mxDestroyArray(copy1);
//copy1 = NULL;
//mexPrintf("\nFreed copy1\n");
/* RESULT: copy2 will still be valid */
//mexPrintf("copy2 = %X, mxGetPr = %X, value = %lf\n",copy2,mxGetPr(copy2),*mxGetPr(copy2));
if (nlhs>0) plhs[0] = mxCreateSharedDataCopy(prhs[0]);
//if (nlhs>0) plhs[0] = const_cast<mxArray*>(prhs[0]);
}
Has any one had before this error message :
Undefined function or method 'name of function' for inputs arguments of type 'double'.
I always have this error message when compiling a mex file. I have checked well the path, and it seems to be the right one.
This is my code, the mex file is amortiss.c
#include "mex.h"
/* The computational functions */
void arrayquotient(double input1, double input2, double output1)
{
output1=input1/input2;
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* variable declarations here */
double input1; /* input scalar 1 */
double input2; /* input scalar 2*/
double output1; /* output scalar 1 */
/* code here */
/* get the value of the scalar input1 */
input1 = mxGetScalar(prhs[0]);
/* get the value of the scalar input2 */
input2 = mxGetScalar(prhs[1]);
/* get the value of the scalar input3 */
input3 = mxGetScalar(prhs[2]);
/* create the output scalar1 */
plhs[0] = mxCreateDoubleScalar(input1/input2);
/* get the value of the scalar output1 */
output1 = mxGetScalar(plhs[0]);
/* call the computational routines */
arrayquotient(input1,input2,output1);
}
I added the path (command add path) to make sure the mex file amortiss.c exists. Then I created a .m file called arrayquotient.m in which I just wrote the declaration of my function :
function c = arrayquotient(a,b)
But, when compiling, another error message appears:
Error in ==> arrayquotient at 1
function c=arrayquotient(a,b)
??? Output argument "c" (and maybe others) not assigned during call to
"C:\Users\hp\Documents\MATLAB\codes_Rihab\arrayquotient.m>arrayquotient".
The function amortiss.c is a c-file and CANNOT be executed as-is by Matlab.
The file, arrayquotient.m, you created is an empty function that does not assign value to its output c.
What you need to do is to mex the c-file amortiss.c to create a mex file amortiss.mexw32 (the extension differs according to your architecture. Use mexext to find out the extension you should be looking for).
In matlab, setup your mex compiler:
>> mex -setup
You will be instructed to choose from compilers installe don your machine and recognized by Matlab.
Once you setup your mex compiler you can go on and mex the c-file
>> mex -O -largeArrayDims amortiss.c
Then you'll have a mex-file amortiss.mexXXX (with 'XXX' depending on your architecture).
You can cll the function like any other function
>> c = amortiss( a, b );