8
$\begingroup$

A ByteArray can be converted to a RawArray:

ba = ByteArray[{1, 2, 3, 4}]
(* ByteArray[{1, 2, 3, 4}] *)

ra = RawArray["Byte", ba]
(* RawArray["UnsignedInteger8",{1, 2, 3, 4}] *)

Normal[ra]
(* {1, 2, 3, 4} *)

Presumably, this is done without unpacking the ByteArray contents to 64-bit integers first (although I have no proof of this).

Is there a similar space-efficient way to convert a rank-1 byte-type RawArray to a ByteArray?

$\endgroup$
1
  • $\begingroup$ The CURLLink package reveals that "ByteArray" is a valid type specification for LibraryFunctionLoad. If anyone is willing to investigate this, it may lead to an answer. $\endgroup$
    – Szabolcs
    Nov 11, 2017 at 13:31

2 Answers 2

7
$\begingroup$

At present there is no way to do this from top level, since there is no interface to the internal function that converts a rank-1 RawArray of bytes into a ByteArray.

However, as already pointed out, it's possible to take advantage of LibraryLink which will do a conversion given an MRawArray on the C side and a "ByteArray" return type, for example

Needs["CCompilerDriver`"]

src = "
  #include \"WolframLibrary.h\"
  #include \"WolframRawArrayLibrary.h\"

  DLLEXPORT mint WolframLibrary_getVersion() {
    return WolframLibraryVersion;
  }

  DLLEXPORT int WolframLibrary_initialize( WolframLibraryData libData) {
    return 0;
  }

  DLLEXPORT void WolframLibrary_uninitialize( WolframLibraryData libData) {
    return;
  }

  DLLEXPORT int mrawarray_to_bytearray( WolframLibraryData libData, 
    mint Argc, MArgument *Args, MArgument Res) {

    WolframRawArrayLibrary_Functions rawFuns = libData->rawarrayLibraryFunctions;
    MRawArray ra;
    mint rank;
    rawarray_t type;

    if (Argc != 1) return LIBRARY_FUNCTION_ERROR;
    ra = MArgument_getMRawArray(Args[0]);

    type = rawFuns->MRawArray_getType(ra);
    rank = rawFuns->MRawArray_getRank(ra);

    if (rank == 1 && type == MRawArray_Type_Ubit8) {
      MArgument_setMRawArray(Res, ra);
      return LIBRARY_NO_ERROR;
    } 
    return LIBRARY_FUNCTION_ERROR;

  }";

lib = CreateLibrary[src, "toByteArray"];

toByteArray = LibraryFunctionLoad[lib, 
  "mrawarray_to_bytearray", {"RawArray"}, "ByteArray"];

toByteArray[RawArray["Byte", {1, 2, 3, 4}]]

(* ByteArray["AQIDBA=="] *)
$\endgroup$
4
  • $\begingroup$ Thank you! I meant to try this, but haven't gotten to it yet, and I really didn't expect it to be as simple as returning an MRawArray as type "ByteArray". $\endgroup$
    – Szabolcs
    Nov 15, 2017 at 16:47
  • $\begingroup$ I was trying to find out which is the earliest version in which this works, so I tried it in 10.4 (first version with RawArray support in LibraryLink). In that version, it only starts working after ByteArray has been used at least once. I.e. if I evaluate ByteArray[{0}] before I try toByteArray, everything is fine. If I don't the first evaluation of toByteArray[RawArray["Byte", {1, 2, 3, 4}]] returns ByteArray[""] (from the second onwards, everything is fine). $\endgroup$
    – Szabolcs
    Nov 15, 2017 at 16:57
  • $\begingroup$ Sounds like a bug (fixed in 11.0). $\endgroup$
    – ilian
    Nov 15, 2017 at 17:03
  • $\begingroup$ Well, it's undocumented, so I wasn't expecting much :-) I also noticed that trying to pass a ByteArray argument using "Constant" passing crashes the kernel. $\endgroup$
    – Szabolcs
    Nov 15, 2017 at 17:29
7
$\begingroup$

The new in M12 function NumericArray is essentially the documented version of the undocumented RawArray. The conversions between ByteArray and NumericArray are straightforward:

ba = ByteArray[{1,2,3,4}];
ba //InputForm

ByteArray["AQIDBA=="]

Conversion to a NumericArray:

na = NumericArray[ba, "Byte"];
na //InputForm

NumericArray[{1, 2, 3, 4}, "UnsignedInteger8"]

Conversion back to a ByteArray:

ba === ByteArray @ na

True

Note that your RawArray syntax is still supported, but it now constructs a NumericArray object instead:

RawArray["Byte", ba] //InputForm

NumericArray[{1, 2, 3, 4}, "UnsignedInteger8"]

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.