How to document a property in Doxygen if the language only supports accessors? - documentation

In C/C++ I usually need to document a property, not only its accessors (getters and setters). Some documentation systems support this directly, for example, GTK-Doc. But how can I do this with Doxygen?
I describe properties in getters, but it's definitely not a solution. Copying the description in both getter and setter is even worse.
A typical C example, where Obj is opaque:
/**
* Doc for getter
*/
int getSize(Obj* obj);
/**
* Doc for setter
*/
void setSize(Obj* obj, int size);
// Where to put the documentation for size itself?

You could do this:
class SomeClass
{
private:
m_size ///< Documentation for the property...
}
See the section "Putting documentation after members" here. Various other comment formats are specified on that page. You can choose the one that best fits what you already have.

Related

Get constants, functions, and protocols from global scope by name

Background
I'm implementing an interface to allow JavaScript to call Objective-C APIs. I'm writing my code in Obj-C++, so can equally use Obj-C or C++ approaches.
Given a string to look up, such as #"NSObject", it's possible to retrieve the class by that name:
// Where `lookupString` is an NSString* such as #"NSObject".
Class clazz = NSClassFromString(lookupString);
I would similarly like to be able to retrieve constants, functions, enums (all data types, really) from the global scope. There are many of these, for example in Foundation:
// 1) A constant (or standalone enumerated value)
// #see https://developer.apple.com/documentation/foundation/1497293-string_encodings/nsasciistringencoding?language=objc
NSASCIIStringEncoding = 1
// 2) An actual enum
// #see https://developer.apple.com/documentation/foundation/nsstringencodingconversionoptions/
typedef enum {
NSAllowLossyEncodingConversion = 1,
NSExternalRepresentationEncodingConversion = 2
} NSStringEncodingConversionOptions;
// 3) A function
// #see https://developer.apple.com/documentation/foundation/1395298-nsstringfromprotocol?language=objc
NSString * NSStringFromProtocol(Protocol *proto);
// 4) A protocol
// #see https://developer.apple.com/documentation/foundation/nsurlconnectiondatadelegate?language=objc
#protocol NSURLConnectionDataDelegate
I am aware of these other obj-c runtime utilities:
NSSelectorFromString (does this solve case #3?)
NSProtocolFromString (clearly solves case #4)
Question
Can all four cases be solved? In other words, how can each of these data types be retrieved from the global scope (or in the scope of an explicitly-named library) at runtime by name alone?

Is that an in or in/out parameter? Doxygen, C++

If a pointer is passed to a function for read only, then this pointer is an IN parameter.
If a pointer is passed to a function for read only, but this function makes a copy of the pointer to have access to it in module related functions for read only operations, this pointer is still IN.
If the function still uses the pointer as read only, but the other module related functions use the pointer for write operations, what does that make the pointer?
An IN parameter, but without const? An in/out parameter?
Example of what I mean:
class SteeringWheel {
public: float rotation;
public: SteeringWheel(void) {
this->rotation = 0.f;
}
};
class Car {
private: SteeringWheel *steeringWheel;
public:
/**
* #param[?] steeringWheel Is the steering wheel in or in/out?
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
/**
* #param[in] degree Steering amount in degrees.
*/
void steer(float degree)
{
this->steeringWheel->rotation += degree;
}
};
int main(int argc, char **argv)
{
SteeringWheel steeringWheel();
/* car() uses steeringWheel as read only. */
Car car(&steeringWheel);
/* steer() uses steeringWheel from car() to write. */
car.steer(50.f);
return 0;
}
I believe that the in and out specifiers do not exactly mean what you think. From the doxygen documentation of the param tag:
The \param command has an optional attribute, (dir), specifying the
direction of the parameter. Possible values are "[in]", "[in,out]",
and "[out]", note the [square] brackets in this description. When a
parameter is both input and output, [in,out] is used as attribute.
The direction of the parameter usually mean the following:
in: The parameter is injected into the function as input, but not written to.
out: The parameter is injected into the function, but not as input. Rather, it is written to by the function.
in, out: The parameter is injected into the function as input and is eventually written to by the function.
In your example:
/**
* #param[?] steeringWheel Is the steering wheel in or in/out?
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
I think the steeringWheel parameter is in because you inject it and use it in your method. However, you never write to it (i.e. to the parameter itself), so it is not out. In other words, you only use your method to inject an address to your function, nothing else. The same apply for your second method, where you inject the degree parameter, but never write to it.
To clarify a bit more on the meaning of in and out, here is an example of an out parameter:
/**
* #param[out] p_param We write to the parameter!
*/
void makeFour(int * p_param)
{
*p_param = 4; // Out because of this line!
}
Notice that we write a new value directly into the parameter. This is the meaning of out: information comes out of the method through the parameter. You can now write:
int main()
{
int myInt = 0;
std::cout << myInt; // prints 0.
makeFour(&myInt); // p_param == &myInt here.
std::cout << myInt; // prints 4: the method wrote directly
// in the parameter (out)!
return 0;
}
Hope this helps!
It is not easy to decide, but I would still mark your parameter as in,out (or out), as it is a pointer to a non-const object, and you may change the state of that outside object directly or indirectly later - as in your example.
Marking it in hides the detail that the pointed SteeringWheel object may change later upon usage of Car.
Also, it can puzzle users why an input only pointer parameter is not marked const.
Making it in,out may not be accurate completely, but is surely more error prone.
An alternative could be something like the following (a note regarding the lifetime of the SteeringWheel should come handy here anyway):
/**
* #param[in] steeringWheel Pointer to the SteeringWheel object.
* #warning The memory address of the pointed object is saved.
* It must outlive this object, and can change upon usage of this object.
*/
Car (SteeringWheel *steeringWheel) {
this->steeringWheel = steeringWheel;
}
But I would just probably stick with marking it in,out.
Specifying the direction of parameters in C++ may be complicated, and frankly speaking, I am not too much in favor of them, as having tokens for pointers, references, and the keyword for constness provide enough information in the signature on how a parameter may be used. Thus, marking it in the DoxyPress documentation is a bit redundant, not expressive enough (as your example shows), and may get out of sync with the implementation. Documenting parameter directions may play a bigger role in case of other languages that lack these additional constructs in function signatures.

Why no stored type properties for classes in swift?

Working through The Swift Programming Language, I was surprised to see that, unlike structures and enumerations, classes do not support stored type properties.
This is a common feature of other OO languages so I assume there was a good reason they decided not to allow it. But I'm not able to guess what that reason is, especially since structures (and enumerations) have them.
Is it simply that it's early times for Swift and it just hasn't been implemented yet? Or is there a deeper reason behind language design decision?
BTW, "stored type property" is Swift terminology. In other languages these might be called class variables. Example code:
struct FooStruct {
static var storedTypeProp = "struct stored property is OK"
}
FooStruct.storedTypeProp // evaluates to "struct stored property is OK"
class FooClass {
class var computedClassProp: String { return "computed class property is OK" }
// class var storedClassProp = "class property not OK" // this won't compile
}
FooClass.computedClassProp // evaluates to "computed class property is OK"
Edit:
I now realize this limitation is trivial to work around, e.g., by using a nested structure with stored properties:
class Foo {
struct Stored {
static var prop1 = "a stored prop"
}
}
Foo.Stored.prop1 // evaluates to "a stored prop"
Foo.Stored.prop1 = "new value"
Foo.Stored.prop1 // evaluates to "new value"
That seems to preclude their being some deep inscrutable language design reason for this limitation.
Given that and the wording of the compiler message that Martin Gordon mentions, I have to conclude that this is simply something (minor) left out.
The compiler error is "Class variables not yet supported" so it seems like they just haven't implemented it yet.
Extending the OP's nested struct trick for simulating stored type properties, you can go further and make it look like a pure stored type property from outside the class.
Use a computed getter and setter pair like:
class ClassWithTypeProperty
{
struct StoredTypeProperties
{
static var aTypeProperty: String = "hello world"
}
class var aTypeProperty: String
{
get { return self.StoredTypeProperties.aTypeProperty }
set { self.StoredTypeProperties.aTypeProperty = newValue }
}
}
Then you can do:
println(ClassWithTypeProperty.aTypeProperty)
// Prints "hello world"
ClassWithTypeProperty.aTypeProperty = "goodbye cruel world"
println(ClassWithTypeProperty.aTypeProperty)
// Prints "goodbye cruel world"
“For value types (that is, structures and enumerations), you can define stored and computed type properties. For classes, you can define computed type properties only."
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/cn/jEUH0.l
I think it's easy for Apple's Engineers to add stored type properties to classes, but not yet we know, maybe never in my opinion. And that's why there are labels ( static and class ) to distinguish them.
The most important reason may be it:
To avoid different objects have shared changeable variable
we know :
static let storedTypeProperty = "StringSample" // in struct or enum ...
can be replaced by
class var storedTypeProperty:String {return "StringSample" } // in class
but
static var storedTypeProperty = "StringSample"
is harder to be replaced by class phrase in class.
// I am new to Swift Programming Language actually and it's my first answer in Stack OverFlow. Glad to discuss with you. ^^

Can a C function be defined within an Objective-C method?

I have a method, like so:
- (void) simpleMethod {
var = someValue;
}
I wanted to define a function which exists only within that method (I can do this in python for example). I tried to define it like a normal C function, like this...
- (void) simpleMethod {
var = someValue;
int times1k(int theVar) {
return theVar * 1000;
}
ivar = times1k(var);
}
But Xcode throws various errors. Is it possible to define a function within a method in Objective-C? And if so, how?
No, Objective-C follows the strict C rules on this sort of thing, so nested functions are not normally allowed. GCC allowed them via a language extension but this extension has not been carried over to Clang and the modern toolchain.
What you can do instead is use blocks, which are Objective-C's version of what Python (and most of the rest of the world) calls closures. The syntax is a little funky because of the desire to remain a superset of C, but your example would be:
- (void) simpleMethod {
var = someValue;
// if you have a bunch of these, you might like to typedef
// the block type
int (^times1k)(int) = ^(int theVar){
return theVar * 1000;
};
// blocks can be called just like functions
ivar = times1k(var);
}
Because that's a closure rather than a simple nested function there are some rules you'd need to follow for declaring variables if you wanted them not to be captured at their values when the declaration is passed over, but none that are relevant to your example because your block is purely functional. Also times1k is a variable that you can in theory pass about, subject to following some unusual rules about memory management (or letting the ARC compiler worry about them for you).
For a first introduction to blocks, I like Joachim Bengtsson's article.

using static c variables in Objective C classes

i have helper C functions in some Objective C classes.
Just found out that the values of global, static C variables which i use in these functions are shared between instances of the class (duh), which is not what i want.
Is there a way to declare these variables local to instances of the class, so that they are visible by the helper functions without passing them explicitly?
Is there a way to declare these variables local to instances of the class
Sure, make them instance variables.
But:
so that they are visible by the helper functions without passing them explicitly?
You can pass the object into the function. If you have appropriate accessors, the function can get them. And if you have mutators, it can modify them, too.
But if you're doing that, you might as well just create a method, and automatically have access to the instance variables.
want to avoid method calls where necessary
logically separate it so your low level code is in c or c++, then add the required data to your objc class:
/* c example */
typedef struct t_generator {
UInt32 a;
} t_generator;
static void Generate(t_generator* const gen) {
/.../
}
#interface MONObjCGeneratorContainer : NSObject
{
t_generator generator;
NSString * name;
UInt32 b;
}
#end
if the data interface is as simple you can just access them from the instance:
- (void)method { GenerateB(&b); }
that should meet all the requirements you have posted (so far).