How to return base64 decoded image bytes through a methods formal parameter of type char**

239 Views Asked by At

Being new to C++, I am still struggling with pointers-to-pointers and I am not sure if my method below is returning decoded image bytes properly.

This method gets a base64 encoded image string from API. The method has to follow this signature as it is part of legacy code that is not allowed to abbreviate from the way it was written originally. So the signature has to stay the same. Also, I have omitted here async calls and continuations, exceptions etc for code simplicity.

int __declspec(dllexport) GetInfoAndPicture(CString uid, char **image, long *imageSize)
{
    CString request = "";
    request.Format(url); 

    http_client httpClient(url);
    http_request msg(methods::POST);

    ...

    http_response httpResponse;
    httpResponse = httpClient.request(msg).get();  //blocking
    web::json::value jsonValue = httpResponse.extract_json().get();

    if (jsonValue.has_string_field(L"img"))
    {
        web::json::value base64EncodedImageValue = jsonValue.at(L"img");
        utility::string_t imageString = base64EncodedImageValue.as_string();  
        std::vector<unsigned char> imageBytes = utility::conversions::from_base64(imageString);
        image = (char**)&imageBytes;  //Is this the way to pass image bytes back? 
    *imageSize = imageBytes.size();
    }

    ...
}

The caller calls this method like so:

char mUid[64];
char* mImage;
long mImageSize;
...
resultCode = GetInfoAndPicture(mUid, &mImage, &mImageSize);

//process image given its data and its size

I know what pointer to pointer is, my question is specific to this line

image = (char**)&imageBytes;

Is this the correct way to return the image decoded from base64 into the calling code via the char** image formal parameter given the above method signature and method call?

I do get error "Program .... File: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp ... "Expression c >= -1 && c <= 255"" which I believe is related to the fact that this line is not correctly passing data back.

2

There are 2 best solutions below

7
On BEST ANSWER

Give the requirements there isn't any way to avoid allocating more memory and copying the bytes. You cannot use the vector directly because that is local to the GetInfoAndPicture function and will be destroyed when that function exits.

If I understand the API correctly then this is what you need to do

//*image = new char[imageBytes.size()];  //use this if caller calls delete[] to deallocate memory
*image = (char*)malloc(imageBytes.size());  //use this if caller calls free(image) to deallocate memory
std::copy(imageBytes.begin(), imageBytes.end(), *image);
*imageSize = imageBytes.size();

Maybe there is some way in your utility::conversions functions of decoding directly to a character array instead of to a vector, but only you would know about that.

0
On

The problem is with allocating (and freeing) memory for that image; who is responsible for that?

You can't (shouldn't) allocate memory in one module and free it in another.

Your two options are:

  1. Allocate large enough buffer on the caller side, and have DLL use it utility::conversions::from_base64(). The issue here is: what is large enough? Some Win APIs provide an additional method to query the required size. Doesn't fit this scenario as the DLL would either have to get that image for the second time, or hold it (indefinitely) until you ask for it.
  2. Allocate required buffer in the DLL and return a pointer to it. You need to ensure that it won't be freed until the caller request to free it (in a separate API).