2

In my C++ native plugin I have a call

vector<unsigned char> getCPPOutput() {
    return some_vector;
}

In my C# side I have the call

[DllImport("MySharedObj")]
static extern byte[] getCPPOutput();

For some reason though I have a mismatch between these two calls, namely if in my C++ I check the size of the array I get as output: 16777216 (for my specific case).

When I check the the size of the byte array I get: 170409961

The call on the C# is really simple, it is something like:

byte[] outputBuffer = getCPPOutput();

There's no preallocation whatsoever. Is there something I need to before calling the function?

I'm not a C# expert at all, it might be I'm missing something very silly.

user8469759
  • 2,522
  • 6
  • 26
  • 50
  • Are you using the `.size` or `.max_size` to check the size of the vector in C++? The vector backing store may be larger than the actual data in the vector, although it would be difficult to imagine that it is that much larger. – Ron Beyer Apr 26 '18 at 15:38
  • @RonBeyer I'm using `.size`. – user8469759 Apr 26 '18 at 16:23

1 Answers1

1

Your return type is byte[] in C# but vector<unsigned char> in C++. These don't match. In your other questions, you were encouraged to fill the array instead of returning it but you still want to return an array, this is how to do it:

Convert the Vector to array then return it. The C++ return type should be char* and the C# return type should be IntPtr. Also, you need a way to tell C# the size of the array. You can do this with an argument. On the C# side, you have to create new array again with the size returned by that argument. After this, use Marshal.Copy to copy the data from IntPtr to that new array.

C++:

char* getCPPOutput(int* outValue)
{
    //Convert the Vector to array
    char* vArrray = &some_vector[0];
    *outValue = some_vector.size();
    return vArrray;
}

C#:

[DllImport("MySharedObj", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr getCPPOutput(out int outValue);


//Test
void Start() 
{
 int size = 0;

 //Call and return the pointer
 IntPtr returnedPtr = getCPPOutput(out size);

 //Create new Variable to Store the result
 byte[] returnedResult = new byte[size];

 //Copy from result pointer to the C# variable
 Marshal.Copy(returnedPtr, returnedResult, 0, size);


 //The returned value is saved in the returnedResult variable

}

Note about your C++ code:

I did not see your some_vector variable declaration. If this is declared in that function as a local variable then it's on the stack and you have to allocate new array dynamically with the new keyword and create a another function to free it with the delete keyword after receiving it on the C# side. You can't return array on the stack unless it is declared as a static object or dynamically allocated with the new keyword.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Well my question is more about "I have this problem, what's the issue beyond it". – user8469759 Apr 26 '18 at 16:27
  • But I got your point, I should preallocate the output on the C# side and fill that array. You're probably right I should do that, I read the answer of my other question only from C# -> C++, not viceversa. – user8469759 Apr 26 '18 at 16:28
  • *"Well my question is more about "I have this problem, what's the issue beyond it""* The return type don't match and that's mentioned in the first sentence of this answer. – Programmer Apr 26 '18 at 21:57