Papierkorb / bindgen

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

Parse and generate nested anonymous structs #90

Closed HertzDevil closed 4 years ago

HertzDevil commented 4 years ago

Implements #85. Nested anonymous structs are copied into separate structures if they name a member, and inlined into their enclosing structures otherwise. No new YAML configurations are added. Also there was nothing for lib Binding structs in SPEC.md so I added some examples there.

I have skipped instance property methods for those anonymous types, because the fictitious type names only exist in the Crystal world, not C++, which requires some extra effort:

struct T {
  struct { int x, y; } point;
  struct { float u, v; }; // inlinable
};

typedef typename std::remove_reference<decltype(std::declval<T>().point)>::type T_Unnamed0; // C++11
// even if we use C++14 return type deduction, the type must still be named in any ctors, like below

extern "C" T_Unnamed0 * bg_T_point_GETTER_(T * _self_) {
  return new (UseGC) T_Unnamed0(_self_->point);
}

// alternatively we could use trailing return type for C++11, decltype is still necessary

template <typename T>
T *bindgen_new_from_copy(const T &x) {
  return new (UseGC) T(x);
}

extern "C" auto bg_T_point_GETTER_(T * _self_) -> decltype(_self_->point) * {
  return bindgen_new_from_copy(_self_->point);
}

On the other hand T#u and T#v are probably doable, and might be required down the road if those members are in a C++ union instead of a struct. These property methods are also skipped in this PR.

These anonymous types are numbered right now, although I wonder if the nested ones can be based on their field names, since every anonymous type is unique. The disadvantage of the current scheme is that they cannot be easily named when clients try to fully construct Binding::Ts themselves. Do you think the alternative scheme would break anything?

Papierkorb commented 4 years ago

👍 Thanks!

Have a nice weekend! 😊