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

ffi not properly decoding Pointer<Char> #152256

Closed
scottandrewzip opened this issue Jul 24, 2024 · 9 comments
Closed

ffi not properly decoding Pointer<Char> #152256

scottandrewzip opened this issue Jul 24, 2024 · 9 comments
Labels
r: solved Issue is closed as solved

Comments

@scottandrewzip
Copy link

Steps to reproduce

I trying to use libiMobileDevice using ffi. However it is having trouble with a structure that is passed into the callback. The structure is defined in C as:

typedef struct {
	enum idevice_event_type event; /**< The event type. */
	const char *udid; /**< The device unique id. */
	enum idevice_connection_type conn_type; /**< The connection type. */
} idevice_event_t;

when i run ffigen i get the following:

final class idevice_event_t extends ffi.Struct {
  /// < The event type.
  @ffi.UnsignedInt()
  external int event;

  /// < The device unique id.
  external ffi.Pointer<ffi.Char> udid;

  /// < The connection type.
  @ffi.UnsignedInt()
  external int conn_type;
}

My callback looks like so:

  void onDeviceChanged(Pointer<idevice_event_t> device, Pointer<Void> data) {
    idevice_event_t event = device.ref;

    var value = event.udid.cast<Utf8>().toDartString();

    log(value);
  }

Expected results

I would expect it to derefernce the string properly.

Actual results

The problem is that the toDartString fails with missing delimiter. When i poke around a bit the codeUnits are not characters but the address of the string (can verify this by looking at the same code in C in a memory viewer). Pointer<Pointer> doesn't work either. How can i properly decode the string. One more hint in the memory viewer the string is not right after the event int. What is after it is a pointer address.

Code sample

Code sample
[Paste your code here]

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[Paste your output here]
@scottandrewzip scottandrewzip changed the title fii not properly decoding Pointer<Char> ffi not properly decoding Pointer<Char> Jul 24, 2024
@dcharkes
Copy link
Contributor

When i poke around a bit the codeUnits are not characters but the address of the string

Then I would have expected:

const char **udid;

And FFIgen would have generated:

external ffi.Pointer<ffi.Pointer<ffi.Char>> udid;

You can try to verify this by modifying the code to be ffi.Pointer<ffi.Pointer<ffi.Char>> and doing .value.toDartString().

Side question: Are you sure your string is UTF-8 encoded? You might simply have an ascii string.
Another side question: I don't know what UDID is, but if it's fixed length it might also not be 0 terminated.

@scottandrewzip
Copy link
Author

I am sure the sting is null terminated and well formed (looked at the memory in XCode). The string is 0 terminated and is all ascii encoded.. I looked at everything in C using Xcode and the memory viewer.

@scottandrewzip
Copy link
Author

scottandrewzip commented Jul 24, 2024

Using the pointer to pointer gives an invalid address for the value..

Pointer (Pointer: address=0xb9401fe8b9001fe0)
address = -5098039693786734624
hashCode = 742544397

Thats not working either. Of course trying to convert to UTF8 fails.. I have to do a value.cast<Utf8> to be able to create dart string. One more strange clue. The conn_type (3rd value in the struct) is not correct in flutter either.

@moffatman
Copy link
Contributor

Hmmm native callback. How are you dealing with threads here?

@dcharkes
Copy link
Contributor

Hmmm native callback. How are you dealing with threads here?

If you're using NativeCallable.listener you need to pass ownership of the pointer to Dart. If the caller from C++ frees the string upon returning, the Dart callback hasn't been run yet (it's queued in the microtask queue, like all async code).

If you're on the Dart thread you can use NativeCallable.isolateLocal.

We don't have support for arbitrary thread blocking callbacks yet (dart-lang/sdk#54554).

@scottandrewzip
Copy link
Author

if I use isolateLocal then i get an error that we can't run callbacks outside the isolate. So basically i need to write some wrappers around the code.

@darshankawar darshankawar added the in triage Presently being triaged by the triage team label Jul 25, 2024
@darshankawar
Copy link
Member

@dcharkes Should this issue move to dart-lang ?

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jul 25, 2024
@dcharkes
Copy link
Contributor

if I use isolateLocal then i get an error that we can't run callbacks outside the isolate. So basically i need to write some wrappers around the code.

👍 Yes, rewriting the code to copy the string and pass ownership to Dart.

cc @liamappelbe another use case of where NativeCallable.blocking would be very nice to have (dart-lang/sdk#54554).

@dcharkes Should this issue move to dart-lang ?

I think this issue can be closed.

@scottandrewzip please let me know if you're still facing issues after passing ownership a copy of the string to Dart.

@darshankawar darshankawar added r: solved Issue is closed as solved and removed waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds in triage Presently being triaged by the triage team labels Jul 25, 2024
Copy link

github-actions bot commented Aug 8, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 8, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
r: solved Issue is closed as solved
Projects
None yet
Development

No branches or pull requests

4 participants