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

Invalid type/array markings #10

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

Invalid type/array markings #10

diamondburned opened this issue Jun 20, 2021 · 2 comments

Comments

@diamondburned
Copy link
Owner

The GIR files have a lot of flaws, and one of them is not marking pointer types
as proper arrays. An example is g_simple_proxy_resolver_set_ignore_hosts,
which is described in the GIR XML file as such:

<!-- Documentation omitted for brevity. -->
<method name="set_ignore_hosts"
        c:identifier="g_simple_proxy_resolver_set_ignore_hosts"
        version="2.36">
  <return-value transfer-ownership="none">
    <type name="none" c:type="void"/>
  </return-value>
  <parameters>
    <instance-parameter name="resolver" transfer-ownership="none">
      <type name="SimpleProxyResolver" c:type="GSimpleProxyResolver*"/>
    </instance-parameter>
    <parameter name="ignore_hosts" transfer-ownership="none">
      <type name="utf8" c:type="gchar**"/>
    </parameter>
  </parameters>
</method>

In this XML block, the ignore_hosts parameter is actually a C array. The
documentation tells you this. However, it is not actually wrapped in an
<array> tag, nor is there any kind of indication that this type is an array
beyond the comments.

A quick and dirty fix for this issue seems to be that the type converters can
simply assume that the type will be a slice. With this, the binding function
signature in Go would be:

func (SimpleProxyResolver) SetIgnoreHosts(ignoreHosts []string)

This also has several advantages. For one, in some GLib/Gio functions that are
used for character set conversion, the caller now has control over weird cases
that are similar to this. For example, the g_ucs4_to_utf16 function expects a
string, but <array> isn't used either.

In some other cases, the type may not actually be an array, but the function
would still expect more than one value of the type be allocated at the pointer's
destination, which is very similar to an array already. If a Go slice were to be
generated, the caller can manually read the comments and allocate an appropriate
slice. This would be much safer than passing in a Go pointer.

In other odd cases, the function may actually want a weird reference somehow,
and the caller will have to somehow unsafely create a Go slice pointing to a
pointer value in order to preserve a copy. Despite this, it may still be a
better idea to carry on regardless, because in the case of SetIgnoreHosts,
have the function parameter type be *string, the function would never actually
work, because the expected array is supposed to be zero-terminated.

Ultimately, none of the solutions listed above are perfect, but the slice
assumption clearly does allow a lot more flexibility, thanks to the pointer
semantics of Go slices. It is therefore a better idea to carry on with that.

Original Comment

// TODO: realistically, the difference between the expected poiner and what C
// wants is only 1. We can work around this.
//
// TODO: ideally, we should treat all foreign pointers as arrays, because they
// usually are. It would also allow the caller to allocate a sized array, as
// they could read the comments.
//
// TODO: there's a way to guess the pointer offset without switch-casing on
// every type. We can do this with IsPrimitive and IsClass fairly easily. We
// will have to account for Go type edge cases, however.
@diamondburned
Copy link
Owner Author

After further thinking, this might not be very ideal, since this assumes that all types that are like this are zero-terminated, which isn't always the case. Perhaps using a raw pointer to the original type is a better idea.

In some cases, APIs that take a pair of (*byte, int) isn't terrible to use; the goal is that, if the pointer rules fail, the generation routine can fall back to generating primitive types with pointers. This should cover most cases.

@diamondburned
Copy link
Owner Author

This issue is superseded by issue #12.

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

No branches or pull requests

1 participant