0

I'm creating a C++ wrapper for a third-party .dll in order to use it with C# P/Invoke. To do so, I have access to a demo application that uses this .dll and as I'm no C expert, I'm heavily dependent on this code. Everything works fine, but a couple of weeks ago, I came across a bit of code that I found rather odd:

unsigned char** ppucValues = new unsigned char*[iSize];
for(int i = 0; i < iSize; i++){
    ppucValues[i] =  (unsigned char *)new int;
    *(int *)ppucValues[i] = piValues[i]; //(piValues is int*)
}

Those lines inside the for-loop puzzled me for a while but looking closely at the first line, I figured "hey, that must mean that an unsigned char is pointing to an int... right?¹"

Yeah, I'm still not so sure about that, but I've used the same concept for several different types and it works. In case anyone is wondering the reason for that, I have to store differently typed values into this unsigned char** and pass it ahead to a method in the third-party .dll that takes, obviously, this unsigned char**. That's how the manufacturer did in their demo app, so I'm just going with it.

With that out of the way, on to my problem: I have to do this same operation but now I'm taking a char** (array of strings) instead of an int* or double* or whatever. Based on what I just said, this is what I came up with:

for(int i = 0; i < iSize ; i++){
    ppucValues[i] = (unsigned char *) new char*; //type of ppucValues as unsigned char** and type of ppucValues[i] as char*???
    *(char **)ppucValues[i] = ppcValues[i]; //Hmmm... what?!
}

But it doesn't work quite as I expected (not to mention that I was just 50% confident on it). For instance, if my input (ppcValues[i]) is "test", my output (ppucValues[i]) turns out as "¨Ô4". I could risk suggesting that this is an encoding issue that has nothing to do with C++ or its pointers, but I'll leave suggestions to the kind people here at StackOverflow. Any help would be appreciated.

¹In case I'm wrong, please enlighten me!

1
  • 1
    new char*; means "allocate a pointer to char"; a pointer is an int; that is 4 or 8bytes (depending on 32/64bits). Commented Apr 14, 2016 at 14:23

2 Answers 2

1

Without more context it's hard to give a definitive solution, but if the lifetime of ppcValues is at least as long (or longer, or course) than ppucValues it is a simple as just copying the pointers, like

for(int i = 0; i < iSize ; i++){
    ppucValues[i] = reinterpret_cast<unsigned char*>(ppcValues[i]);
}

If the lifetime of ppcValues is shorter than the lifetime of ppucValues, then you need to allocate enough memory to fit all the data in ppcValues[i] and copy it:

for(int i = 0; i < iSize ; i++){
    ppucValues[i] = new unsigned char[length_of(ppcValues[i])];
    std::copy_n(reinterpret_cast<unsigned char*>(ppcValues[i]), ppucValues[i], length_of(ppcValues[i]));
}

The length_of function depends on the contents of ppcValues[i]. If it's a C-style string then you should be using strlen(ppcValues[i]) + 1.

Also note that if you allocate using new[] then you need to be freeing with delete[].

Sign up to request clarification or add additional context in comments.

1 Comment

Fantastic, your first example runs smoothly... Or rather... It's reinterpret_cast, not reinterpret_char, but that was an honest mistake! Many thanks!
0

But it doesn't work quite as I expected

That's because strings, i.e. null terminated char*s, are not the same as the fundamental types. You are passing a pointer. If the memory the pointer points to gets deallocated or overwritten by some code before it is processed by the users of ppucValues, then you are looking at undefined behavior.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.