Papierkorb / bindgen

Binding and wrapper generator for C/C++ libraries
GNU General Public License v3.0
179 stars 18 forks source link

Preliminary support for C arrays #76

Open HertzDevil opened 4 years ago

HertzDevil commented 4 years ago

Adds support for C array types, i.e. int [4][3][2]. It is not to be confused with std::array.

Optional features:

This patch also fixes what I believe to be a bug where CopyStructs converts void ** fields to a plain void *.

Papierkorb commented 4 years ago

Map C array constants to Crystal Arrays, provided they only contain other supported constants (Int | Float | String | Bool).

I don't think we need that, Slices are fine. They're easy to get into an array if needed, otherwise bindgen should prefer lower overhead. Could be an opt-in feature however.

Good stuff as always, cheers!

HertzDevil commented 4 years ago

About struct CrystalSlice: When I tried to attach the element type to it as a template parameter, I got errors like this:

instance_properties.cpp:57:30: error: 'bg_Props_v_GETTER_' has C-linkage specified, but returns incomplete type 'CrystalSlice<int>' which could be incompatible with C [-Werror,-Wreturn-type-c-linkage]
extern "C" CrystalSlice<int> bg_Props_v_GETTER_(Props * _self_) {

How did CrystalProc get around this?

Also it seems the PR is already quite large, so I'm calling it done once I add the documentation. General methods could wait a bit longer. (Most C array arguments in practice are just T [] => T * anyway.)

HertzDevil commented 4 years ago

Putting this PR on hiatus because there is one major problem: slices can only refer to binding types even when the element type is wrapped. For example:

struct Inner {
  char a;
};

struct Outer {
  Inner b[4];
  Inner *c[5];
};
module Test
  lib Binding
    alias Inner = Void
  end

  class Inner
    @unwrap : Binding::Inner*

    def initialize(unwrap : Binding::Inner*)
    end
  end

  class Outer
    def b() : Slice(Binding::Inner)
      # Slice(Void) not allowed
      # copying Inner's structure might work
    end

    def c() : Slice(Binding::Inner*)
      # ::Slice#[] returns a raw pointer; it won't call Inner#initialize
    end
  end
end

One possible solution is to return a custom Slice-like type instead of the core library's one. This in turn could leverage BindgenHelper::SequentialContainer, but at this moment I don't have any plans of getting that to work (at the very least the custom Slice would not have #<<).

Papierkorb commented 4 years ago

That sounds reasonable, still dang, didn't think about that either. I think that indeed, a custom Enumerable will be what we want for this.

HertzDevil commented 4 years ago

That's it for now, Bindgen will currently reject arrays that are not built-in types (more specifically getter methods are omitted, and lib structs containing them are reported by SanityCheck).

Papierkorb commented 4 years ago

Could you resolve the conflict? LGTM after that 👍

docelic commented 3 years ago

I'll try to resolve the conflicts here during this weekend; @HertzDevil if you have any comments/notes re. that, please share. Thanks!