[GH-ISSUE #148] QByteArray support #92

Closed
opened 2026-05-05 11:04:16 -06:00 by gitea-mirror · 6 comments
Owner

Originally created by @geigertom on GitHub (Jul 1, 2019).
Original GitHub issue: https://github.com/qmlnet/qmlnet/issues/148

I'm trying to pass a QByteArray containing raw image data to my registered .net object by attaching to the emitted signal of a QVideoFilter that I wrote in c++.

QByteArray byteArray = byteArrayFromImage(img);
emit m_filter->finished(byteArray);

The connection works, and I can pass objects, e.g. QString to the signal listener:

var handler = qVideoFilter.AttachSignal("finished", parameters => {
    Console.WriteLine("onFinished: " + parameters );
});

But apparently QByteArray is not (yet) supported:

Unsupported variant type: QVariant::QByteArray QByteArray

I tried converting it to a QVariantList beforehand, which actually works, but the conversion on each frame takes far to much time to be usable in real time image processing.

Is it possible to pass QByteArray or a simple byte array to .net? What would be the aproach to extend qml.net to support types like QByteArray? I would love to help implement this feature but I need a little push in the right direction.

Thanks,
Tom

Originally created by @geigertom on GitHub (Jul 1, 2019). Original GitHub issue: https://github.com/qmlnet/qmlnet/issues/148 I'm trying to pass a QByteArray containing raw image data to my registered .net object by attaching to the emitted signal of a QVideoFilter that I wrote in c++. ``` QByteArray byteArray = byteArrayFromImage(img); emit m_filter->finished(byteArray); ``` The connection works, and I can pass objects, e.g. QString to the signal listener: ``` var handler = qVideoFilter.AttachSignal("finished", parameters => { Console.WriteLine("onFinished: " + parameters ); }); ``` But apparently QByteArray is not (yet) supported: `Unsupported variant type: QVariant::QByteArray QByteArray` I tried converting it to a QVariantList beforehand, which actually works, but the conversion on each frame takes far to much time to be usable in real time image processing. Is it possible to pass QByteArray or a simple byte array to .net? What would be the aproach to extend qml.net to support types like QByteArray? I would love to help implement this feature but I need a little push in the right direction. Thanks, Tom
Author
Owner

@pauldotknopf commented on GitHub (Jul 1, 2019):

This is interesting.

I'd say just pass a pointer to the raw byte array, but QByteArray is ref counted, and it may be deleted from underneath you. You'd definately want to maintain an instance of QByteArray to copy the contents to a .net array at a later time.

Adding this support would be easy.

I'd say update NetVariant to support a new NetVariantType of QByteArray. Then you'd have NetVariant.SetBytes(byte[]) and byte[] NetVariant.GetBytes()```.

However, this means that you'll never be able to modify QByteArray from .NET, since you'd only be sending receiving raw .NET byte arrays.

If you need the instance of QByteArray in .NET so that you could maybe pass the raw pointer somewhere else, or modify it directly, you could implement something like INetJsValue, but call it INetQByteArray. That would have methods for you to modify the internal instance of QByteArray.

What approach would be best for you? We could support both.

<!-- gh-comment-id:507380309 --> @pauldotknopf commented on GitHub (Jul 1, 2019): This is interesting. I'd say just pass a pointer to the raw byte array, but QByteArray is ref counted, and it may be deleted from underneath you. You'd definately want to maintain an instance of QByteArray to copy the contents to a .net array at a later time. Adding this support would be easy. I'd say update [```NetVariant```](https://github.com/qmlnet/qmlnet/blob/develop/src/net/Qml.Net/Internal/Qml/NetVariant.cs) to support a new ```NetVariantType``` of ```QByteArray```. Then you'd have ```NetVariant.SetBytes(byte[]) and ```byte[] NetVariant.GetBytes()```. However, this means that you'll never be able to modify ```QByteArray``` from .NET, since you'd only be sending receiving raw .NET byte arrays. If you need the instance of ```QByteArray``` in .NET so that you could maybe pass the raw pointer somewhere else, or modify it directly, you could implement something like [```INetJsValue```](https://github.com/qmlnet/qmlnet/blob/develop/src/net/Qml.Net.Tests/Qml/JsValueTests.cs), but call it ```INetQByteArray```. That would have methods for you to modify the internal instance of ```QByteArray```. What approach would be best for you? We could support both.
Author
Owner

@geigertom commented on GitHub (Jul 2, 2019):

For my use case I don't need an instance of the QByteArray in .NET, a raw .NET byte array would be just fine. I will take a look at NetVariant and see what I can do to extend it the way you suggested.

<!-- gh-comment-id:507564454 --> @geigertom commented on GitHub (Jul 2, 2019): For my use case I don't need an instance of the `QByteArray` in .NET, a raw .NET byte array would be just fine. I will take a look at `NetVariant` and see what I can do to extend it the way you suggested.
Author
Owner

@pauldotknopf commented on GitHub (Jul 2, 2019):

You'd have to marshal that yourself, it isn't blittable. The best bet would be to make net_variant_getBytes take in a c-style callback that passes in raw pointer and the number of bytes, for you to then marshal in .NET.

<!-- gh-comment-id:507814519 --> @pauldotknopf commented on GitHub (Jul 2, 2019): You'd have to marshal that yourself, it isn't blittable. The best bet would be to make ```net_variant_getBytes``` take in a c-style callback that passes in raw pointer and the number of bytes, for you to then marshal in .NET.
Author
Owner

@pauldotknopf commented on GitHub (Jul 2, 2019):

net_variant_getBytes(variant, (pointer, count) { /*.NET code to convert IntPtr to byte array*/ })
<!-- gh-comment-id:507814943 --> @pauldotknopf commented on GitHub (Jul 2, 2019): ``` net_variant_getBytes(variant, (pointer, count) { /*.NET code to convert IntPtr to byte array*/ }) ```
Author
Owner

@geigertom commented on GitHub (Jul 2, 2019):

Thanks, I realize that I need to read more on the concept of marshalling to gain a better understanding.

<!-- gh-comment-id:507836425 --> @geigertom commented on GitHub (Jul 2, 2019): Thanks, I realize that I need to read more on the concept of marshalling to gain a better understanding.
Author
Owner

@geigertom commented on GitHub (Jul 3, 2019):

I finally got it working:

Q_DECL_EXPORT LPARRAY net_variant_getBytes(NetVariantContainer* container, int &count) {
    const QByteArray byteArray = container->variant->getBytes();
    count = byteArray.count();;
    return byteArray.constData();
}
public byte[] ByteArray
{
    get {
        int count;
        IntPtr arrayHandle = Interop.NetVariant.GetBytes(Handle, out count);
        byte[] managedArray = new byte[count];
        Marshal.Copy(arrayHandle, managedArray, 0, count);
        return managedArray;
    }
}

I will create a PR in the next few days as soon I find the time.

<!-- gh-comment-id:508011974 --> @geigertom commented on GitHub (Jul 3, 2019): I finally got it working: ``` Q_DECL_EXPORT LPARRAY net_variant_getBytes(NetVariantContainer* container, int &count) { const QByteArray byteArray = container->variant->getBytes(); count = byteArray.count();; return byteArray.constData(); } ``` ``` public byte[] ByteArray { get { int count; IntPtr arrayHandle = Interop.NetVariant.GetBytes(Handle, out count); byte[] managedArray = new byte[count]; Marshal.Copy(arrayHandle, managedArray, 0, count); return managedArray; } } ``` I will create a PR in the next few days as soon I find the time.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/qmlnet#92
No description provided.