Description
The Problem
According to this cgo documentation, when exporting functions using cgo, the resulting header file should retain your function parameters names, however it practice it does not.
It States
Go functions can be exported for use by C code in the following way:
//export MyFunction func MyFunction(arg1, arg2 int, arg3 string) int64 {...} //export MyFunction2 func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}They will be available in the C code as:
extern int64 MyFunction(int arg1, int arg2, GoString arg3); extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
However, when I compile that exact code it gave, i get this result:
extern GoInt64 MyFunction(GoInt p0, GoInt p1, GoString p2);
extern struct MyFunction2_return MyFunction2(GoInt p0, GoInt p1, GoString p2);
While this documentation that i've linked is wrong both in the types it assigns to the parameters and their return types and the way that their names are exported (should probably be updated), the documentation isn't really the focus of my proposal.
Based on this stack overflow thread I had posted a while back, it seems that the reason for this is that "Go allows arbitrary rune names, e.g., instead of input
you might call the variable π
. C does not allow such names."
My Proposal
Instead of avoiding this using parameter names such as p0
, p1
, p2
, etc, we first detect if the function name is using a non-ASCII character in its name using something like this (taken from this SO thread)
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] > unicode.MaxASCII {
return false
}
}
return true
}
And then we could do one of several things.
- Export all non-ASCII parameters as they are now using
p0
,p1
, etc, but allow parameter names that are proper ASCII to use their original names. - Remove the non-ASCII characters from the parameter name and print a warning during compilation.
- Do not allow parameter names that include non-ASCII characters in C exported functions, but allow them in regular go functions. (this is my preference)
- I'm open to other solutions?
This normally wouldn't be an issue, but when a functions documentation block doesn't line up properly with the parameter names for the function, you wind up with incorrect documentation in either the source file or in the exported header, and it interferes with consumption of the exported header file.
Here is a basic example that somewhat demonstrates how the documentation can become misaligned.
/**
* Parses the name based on the type.
*
* @param type the type
* @param name the name
*/
//export ParseValue
func ParseValue(type C.int, name *C.char) {
// do something with the data
}
results in
/**
* Parses the name based on the type.
*
* @param type the type
* @param name the name
*/
extern void ParseValue(int p0, char* p1);
Consuming that function externally might not be incredibly difficult if you infer the position of the parameters, but when you have functions with much more complex signatures or functions with parameter documentation out of order, things get hairy and it tends to result in you maintaining documentation that does not line up either in source or does not line up in implementation.
I personally think the best solution would be to remove the allowance of runes in functions that are exported through cgo specifically. This way function parameters will line up in the C header and the Go source file and add a much needed congruity.