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

ObjC: Should generate a custom method to allow efficient exchange of data with NSData. #283

Closed
brianquinlan opened this issue May 20, 2022 · 1 comment
Labels
lang-objective_c Related to Objective C support package:ffigen package:objective_c type-enhancement A request for a change that isn't a bug

Comments

@brianquinlan
Copy link
Contributor

Conceptually something like this:

class NSData  extends NSObject {
  factory Data.fromUint8List(Uint8List l) {
    final f = pffi.calloc<ffi.Uint8>(l.length);
    try {
      f.asTypedList(l.length).setAll(0, l);

      return NSData.dataWithBytes_length_(_lib, f.cast(), l.length);
    } finally {
      pffi.calloc.free(f);
    }
  }

  Uint8List get uInt8List {
    final rawBytes = bytes;
    if (rawBytes.address == 0) {
      return Uint8List(0);
    } else {
      // This is unsafe! It is only a view into the underlying NSData!
      return rawBytes.cast<ffi.Uint8>().asTypedList(length);
    }
  }
}

I think that the memory unsafety can be fixed with some effort:

class _NSDataUint8List implements Uint8List, Finalizable {
...
}

  Uint8List get uInt8List {
    final rawBytes = bytes;
    if (rawBytes.address == 0) {
      return Uint8List(0);
    } else {
      retain(); // Keep a reference alive so long as the data is being accessed.
      final uintList = _NSDataUint8List(rawBytes.cast<ffi.Uint8>().asTypedList(length));
      finalizer.attach(uintList, ....) // calls release on this NSData instance.
      return uintList;
    }
  }
}
@brianquinlan brianquinlan added type-enhancement A request for a change that isn't a bug lang-objective_c Related to Objective C support labels May 20, 2022
@liamappelbe liamappelbe transferred this issue from dart-archive/ffigen Nov 15, 2023
HosseinYousefi pushed a commit that referenced this issue Nov 16, 2023
HosseinYousefi pushed a commit that referenced this issue Nov 16, 2023
parlough pushed a commit to parlough/native that referenced this issue Apr 8, 2024
Unify and simplify how Types are cached and cycles are broken in the type graph.

- All types that need to be cached (those that have a declaration cursor) are cached in `BindingsIndex._declaredTypes`
- All calls to convert a `CXType` to an ffigen `Type` now go through `getCodeGenType`
- All calls to the related sub-parsers (`parseCompoundDeclaration`, `parseEnumDeclaration`, `parseTypedefDeclaration`) also go through `getCodeGenType`
- Those sub-parsers (mostly) don't know about `BindingsIndex`, and don't know about caching or cycle breaking. That's all handled in one place in `getCodeGenType`
- Cycles are broken by dividing type conversion into 2 stages (the only conversion this matters for is compound types):
    - First the `Type` is created, with as many fields filled in as possible, without a recursive call to `getCodeGenType` (everything except the list of members)
    - Next, `getCodeGenType` inserts the type into the cache
    - Finally, the members are filled in. Recursive calls to `getCodeGenType` are allowed here, as they will hit the cache, breaking any cycles.
@liamappelbe
Copy link
Contributor

These helpers were added in #1104
They're somewhat inefficient at the moment, but making them more efficient is tracked here: #1107

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lang-objective_c Related to Objective C support package:ffigen package:objective_c type-enhancement A request for a change that isn't a bug
Projects
Status: Done
Development

No branches or pull requests

2 participants