-
Notifications
You must be signed in to change notification settings - Fork 42
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
Have trouble when covert Array<UnsignedChar> to Dart String. #1601
Comments
How are you getting an instance of that struct? Assuming you're getting it from some function like |
@liamappelbe I have found out the reason why the string is wrong. The string is correct when I use it inside the I think I can‘t use the ref struct after the pointer is freed? final cap = ffi.using((arena) {
final capPtr = arena<ffi.v4l2_capability>();
final error = ffi.libV4L2.ioctl(device.fd, ffi.VIDIOC_QUERYCAP, capPtr);
if (error == -1) {
throw V4L2Error('ioctl failed, $error.');
}
// Here the driver is correct.
print(capPtr.ref.driver.dartValue);
return capPtr.ref;
});
// Here the driver is wrong.
print(cap.driver.dartValue); |
Yeah, the struct won't be valid anymore after the backing storage is deleted. I'm doing something similar to return structs by value in this PR. You could try switching to this pattern instead (note how /// twiddleVec4Components:
Vec4 twiddleVec4Components_(Vec4 v) {
final _ptr = pkg_ffi.calloc<Vec4>();
final _data = _ptr
.cast<ffi.Uint8>()
.asTypedList(ffi.sizeOf<Vec4>(), finalizer: pkg_ffi.calloc.nativeFree);
objc.useMsgSendVariants
? _objc_msgSend_5Stret(
_ptr, this.ref.pointer, _sel_twiddleVec4Components_, v)
: _ptr.ref =
_objc_msgSend_5(this.ref.pointer, _sel_twiddleVec4Components_, v);
return ffi.Struct.create<Vec4>(_data);
} |
@dcharkes Would it make sense to add a util in package:ffi that does this allocation dance? I tried writing a util to use in the ffigen bindings, but I think it'll need some CFE magic. In that snippet, if you try to make that allocation generic (ie swap out |
Offtopic: It would be better to move
So you mean a util in
You can't use Maybe we could add a pattern that does the |
@dcharkes @liamappelbe I kept the struct pointer and use Finalizer and Finalizable to keep the memory safe like this. final finalizer = ffi.NativeFinalizer(ffi.malloc.nativeFree);
/* V4L2Format */
abstract base class V4L2FormatImpl implements V4L2Format {
V4L2FormatImpl();
factory V4L2FormatImpl.managed() => _ManagedV4L2FormatImpl();
ffi.v4l2_format get ref;
V4L2BufType get type => ref.type.toDartBufType();
set type(V4L2BufType value) => ref.type = value.value;
@override
V4L2PixFormat get pix => V4L2PixFormatImpl.unmanaged(ref.fmt.pix);
@override
set pix(V4L2PixFormat value) {
if (value is! V4L2PixFormatImpl) {
throw TypeError();
}
ref.fmt.pix = value.ref;
}
}
final class _ManagedV4L2FormatImpl extends V4L2FormatImpl
implements ffi.Finalizable {
final ffi.Pointer<ffi.v4l2_format> ptr;
_ManagedV4L2FormatImpl() : ptr = ffi.malloc() {
finalizer.attach(
this,
ptr.cast(),
);
}
@override
ffi.v4l2_format get ref => ptr.ref;
}
/* V4L2PixFormat */
abstract base class V4L2PixFormatImpl implements V4L2PixFormat {
V4L2PixFormatImpl();
factory V4L2PixFormatImpl.unmanaged(ffi.v4l2_pix_format ref) =>
_UnmanagedV4L2PixFormatImpl(ref);
factory V4L2PixFormatImpl.managed() => _ManagedV4L2PixFormatImpl();
ffi.v4l2_pix_format get ref;
@override
int get width => ref.width;
@override
set width(int value) => ref.width = value;
@override
int get height => ref.height;
@override
set height(int value) => ref.height = value;
@override
V4L2PixFmt get pixelformat => ref.pixelformat.toDartPixFmt();
@override
set pixelformat(V4L2PixFmt value) => ref.pixelformat = value.value;
@override
V4L2Field get field => ref.field.toDartField();
@override
set field(V4L2Field value) => ref.field = value.value;
}
final class _UnmanagedV4L2PixFormatImpl extends V4L2PixFormatImpl {
@override
final ffi.v4l2_pix_format ref;
_UnmanagedV4L2PixFormatImpl(this.ref);
}
final class _ManagedV4L2PixFormatImpl extends V4L2PixFormatImpl
implements ffi.Finalizable {
final ffi.Pointer<ffi.v4l2_pix_format> ptr;
_ManagedV4L2PixFormatImpl() : ptr = ffi.malloc() {
finalizer.attach(
this,
ptr.cast(),
);
}
@override
ffi.v4l2_pix_format get ref => ptr.ref;
} And use it like this: @override
V4L2Format gFmt(int fd) {
// TODO: add more types.
final fmt = _ManagedV4L2FormatImpl()..type = V4L2BufType.videoCapture;
final err = ffi.libV4L2.ioctlV4l2_formatPtr(fd, ffi.VIDIOC_G_FMT, fmt.ptr);
if (err != 0) {
throw V4L2Error('ioctl `VIDIOC_G_FMT` failed, $err.');
}
return fmt;
} I think the native memory can be freed automatically when the dart instance finalized, am I right? |
Recently I'm working on using ffigen to call v4l2 on linux, there is a v4l2_capability Struct which is generated like this:
The corresponding c struct is:
And I convert the Array to String as followed:
When I run the app, the card and bus_info are correct, but the driver field is always incorrect and changed every time I run the code.
Here is the logs
The text was updated successfully, but these errors were encountered: