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

Add string class FFI::C::String + FFI::C::StringDef #9

Open
plicease opened this issue Apr 28, 2020 · 1 comment
Open

Add string class FFI::C::String + FFI::C::StringDef #9

plicease opened this issue Apr 28, 2020 · 1 comment
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@plicease
Copy link
Member

This would wrap around a pointer to a null terminated C style string. Some integration with opaque member on a struct/union would be helpful.

@plicease plicease added enhancement New feature or request help wanted Extra attention is needed labels Apr 28, 2020
@plicease
Copy link
Member Author

plicease commented May 2, 2023

Update: I still haven't had time to circle back to this, but the fundamental challenge is that I am not sure exactly how to do the ownership of this object type if it is going to be used as a member of an FFI::C::Struct (or FFI::C::Union, which could be quite complicated). The pattern used elsewhere in FFI::C is that if the pointer was allocated in C space it should not be free'd automatically, but it was allocated in Perl space it should be free'd when the object falls out of scope. This is easy to deal with for nested data, but more complicated with pointers. The eventual goal here is to have an FFI::C::String that could be used when defining members of an FFI::C::Struct or FFI::C::Array.

The work around for now is to use an opaque pointer and write a accessor method that converts from/to opaque as appropriate: (caveat example code has not been tested for syntax or anything like that)

package Foo {
  FFI::C->struct([
    _string_ptr   => 'opaque',
  ]);

  # read-only, for data allocated and free'd in C space
  sub string ($self)
  {
    $ffi->cast('opaque', 'string', $self->_string_ptr);
  }
}
package Foo {

  use FFI::Platypus::Memory qw( free strdup );

  FFI::C->struct([
    _string_ptr   => 'opaque',
  ]);

  # read-write, for data allocated and free'd in Perl space
  sub string ($self, $new_value=undef)
  {
    if(defined $new_value) {
      if(defined $self->_string_ptr) {
        free $self->_string_ptr;
      }
      $self->_string_ptr(strdup $new_value);
    }
    $ffi->cast('opaque', 'string', $self->_string_ptr);
  }

  sub string_free ($self)
  {
    if(defined $self->_string_ptr) {
      free $self->_string_ptr;
      $self->_string_ptr(undef);
    }
  }
}

Another option is to use FFI::Platypus::Record, which has both string_ro and string_rw types, where the assumption is that for string_ro C owns the data and is therefore read-only and not free'd by Perl, and that for string_rw Perl owns the data and is therefore read-write and IS free'd by Perl when the record falls out of scope. We could in theory do something similar for FFI::C but that doesn't seem like the right approach for FFI::C

Whatever approach we eventually decide on, we have to consider how to handle pointers to strings in Unions. I don't think there is an obvious automatic way to do it, and we might just have to disallow string pointers inside of a union. If you need that capability you can still define an opaque pointer member and manage the reads by casting and allocation manually.

None of this applies to a fixed length string, which is nested inside of a struct, this sort of data structure is basically the same as a fixed array of char.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Development

No branches or pull requests

1 participant