Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more conservative in converting types #12

Closed
diamondburned opened this issue Jun 20, 2021 · 2 comments
Closed

Be more conservative in converting types #12

diamondburned opened this issue Jun 20, 2021 · 2 comments
Labels
enhancement New feature or request

Comments

@diamondburned
Copy link
Owner

Currently, gotk4 converts types back and forth primarily using 2 ways: either by directly casting the value or resorting to functions like C.CString or C.GoString. For the most part, this works great.

However, in some cases, the GIR files contain weird pointer requirements. For example, a badly annotated function parameter may require gchar** to denote an array without actually using an <array> tag. This confuses C.GoString().

An attempt to fix this was using the convertRef routine, which handled this in a slight convoluted (and very incorrect) way. It requires the conversion routine to specify the pointers it accepts and returns, and the convertRef routine will generate the appropriate reference and dereference code. This theoretically sounds like a good idea, however realistically, there is rarely ever a case where the pointer difference is more than 1. Also, in most cases, parameters like that have some special meaning to them that the code cannot guess.

Because unusual pointer requirements usually have a special meaning, the conversion routine cannot assume anything about it. This includes gchar**. Instead, the conversion routine should preserve the original type **byte, even though it might seem ugly. This gives the caller the control over how things should work, which is good, because humans can parse documentation, and machines cannot (trivially).

For example, if a function expects gchar** and the documentation states that it is a null-terminated array of strings, the caller can do this:

strings := make([][]byte, len(input)+1) // null-terminated
for i, str := range strings {
    input[i] = []byte(str + "\x00") // null-terminated
}
FunctionName(&strings[0])

If the type conversion routine can be more conservative like this, then there wouldn't be a need for a convertRef routine. Instead, the conversion routine could simply only handle strings, errors and whatnot only when the conditions match up, which is most of the time.

This approach only applies to primitive types. This means that, for classes (like GtkWidget) or records (like GError), an unusual pointer requirement will force the converter to skip, as the implementation difference has to be handled internally in order to not leak the C type.

This was referenced Jun 20, 2021
@diamondburned diamondburned added broken Changes that require refactoring enhancement New feature or request and removed broken Changes that require refactoring labels Jun 20, 2021
@diamondburned
Copy link
Owner Author

This was not explicitly mentioned above, but in order to handle [][]byte, a generator still has to be made. Just taking the backing array pointer will not work as gchar**, as the slice's underlying value has more than just a pointer. This conversion does not require knowing the length or terminator, however, since it can naively malloc enough memory from the given slice's length at runtime.

@diamondburned
Copy link
Owner Author

The conversion routine now allows some leeway with a ±1 pointer difference in most cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant