ruby / fiddle

A libffi wrapper for Ruby.
BSD 2-Clause "Simplified" License
154 stars 37 forks source link

parse_ctype() fails for "int long len" #100

Closed dmlary closed 1 year ago

dmlary commented 2 years ago

parse_ctype() does not handle int long len correctly; errors with unknown type: int

[22] pry(#<Fiddle::CastXMLImporter::Importer>)> parse_struct_signature(["char id", "int long size"])
Fiddle::DLError: unknown type: int
from /Users/dmlary/.rbenv/versions/3.0.2/lib/ruby/3.0.0/fiddle/cparser.rb:245:in `parse_ctype'
[24] pry(#<Fiddle::CastXMLImporter::Importer>)> parse_ctype("int long size")
Fiddle::DLError: unknown type: int
from /Users/dmlary/.rbenv/versions/3.0.2/lib/ruby/3.0.0/fiddle/cparser.rb:245:in `parse_ctype'
[25] pry(#<Fiddle::CastXMLImporter::Importer>)> parse_ctype("int long")
=> 4

I am aware that I can switch the field definition to long, but these types are being pulled out of CastXML, and I'd prefer to fix the bug in Fiddle instead of implementing a bunch of type remapping.

old

parse_struct_signature() is passing the complete struct member definition to parse_ctype(). This includes both the ctype and the member name. This causes a problem when handling structs that contain compound members such as: int long length in their definition.

dmlary commented 2 years ago

Oof, ok the fix for this is non-trivial. The ordering that comes out of CastXML (from the clang AST), is different for most of these types. It would require reworking parse_ctype() to handle unsigned and long at any point along the type string.

As an example of why this is difficult, each of these types are equivalent and valid, but only one of them is covered in parse_ctype():

For reference, here is the list of types that CastXML is using for one of my source files:

  <FundamentalType id="_676" name="__int128" size="128" align="128"/>
  <FundamentalType id="_677" name="unsigned __int128" size="128" align="128"/>
  <FundamentalType id="_697" name="void" size="0" align="8"/>
  <FundamentalType id="_702" name="unsigned char" size="8" align="8"/>
  <FundamentalType id="_703" name="short unsigned int" size="16" align="16"/>
  <FundamentalType id="_704" name="unsigned int" size="32" align="32"/>
  <FundamentalType id="_705" name="long unsigned int" size="64" align="64"/>
  <FundamentalType id="_706" name="signed char" size="8" align="8"/>
  <FundamentalType id="_707" name="short int" size="16" align="16"/>
  <FundamentalType id="_708" name="int" size="32" align="32"/>
  <FundamentalType id="_709" name="long int" size="64" align="64"/>
  <FundamentalType id="_860" name="char" size="8" align="8"/>
  <FundamentalType id="_1436" name="long long int" size="64" align="64"/>
  <FundamentalType id="_1455" name="float" size="32" align="32"/>
  <FundamentalType id="_1494" name="long double" size="128" align="128"/>
  <FundamentalType id="_1528" name="long long unsigned int" size="64" align="64"/>

Instead of trying to fix this in fiddle, I'm just going to map the CastXML types into u?int\d+_t.