Reputation: 4125
I am trying to pass an array of byte
from Blazor Client to a javascript function:
private async void ShowImage()
{
SelectedImageBytes = await GetImageData();
if (SelectedImageBytes.Any())
{
ReceivedDataLength = SelectedImageBytes.Length;
//ReceivedDataLength is 131072, which is correct
JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
}
StateHasChanged();
}
On Javascript side:
function setImage(data, width, height)
{
console.log("On Javascript I have received an array of " + data.length);
//data.length is 174764
console.log(data);
//...
}
console.log(data)
outputs the following:
Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764
My questions then are:
Upvotes: 3
Views: 3014
Reputation: 4125
I gave it another go:
C#
public void CallJsUnMarshalled()
{
var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;
unmarshalledRuntime.InvokeUnmarshalled<byte[], int>("JsFunctions.MyFunctionUnmarshalled", MyBytes);
}
Javascript:
function MyFunctionUnmarshalled(bytes)
{
const dataPtr = Blazor.platform.getArrayEntryPtr(bytes, 0, 4);
const length = Blazor.platform.getArrayLength(bytes);
var shorts = new Int16Array(Module.HEAPU8.buffer, dataPtr, length);
return 0;
}
InvokeUnmarshalled
requires a return it appears, therefore int
in the template arguments. Instead of this probably a reference to the object has to be returned to dispose it. I would appreciate if someone can comment on this (will javascript free that memory when the byte array is not used anymore?).
First tests show an improvement of a factor of 50!
Upvotes: 4
Reputation: 2601
When you are using the interop service, the documentation says:
InvokeAsync takes an identifier for the JavaScript function that you wish to invoke along with any number of JSON-serializable arguments.
So what you observe is the serialization of your byte array into a base64 string, which is the out-of-the-box behavior. So, you are right. I haven't spotted a way to influence the serialization behavior of the JSInterop service.
The Blazer framework in .NET 5 offers you a way to skip the serialization overhead: IJSUnmarshalledRuntime.
But, in my experiments, it can't handle a byte array or any arrays at all.
To answer your second question, have a look at this discussion.
Convert base64 string to ArrayBuffer
Upvotes: 2