I uploaded some sample code on GitHub, that shows how to create safe arrays in C++ and consume them in a C# application.
This project contains a C++ DLL (with a C interface) that exports two functions to produce safe arrays containing bytes and strings.
Then, there’s a WinForms C# application that consumes these safe arrays using proper PInvoke declarations, and shows their content on screen.
Suppose you have a vector<string> in some cross-platform C++ code, and you want to marshal it across module or language boundaries on the Windows platform: Using a safe array is a valid option.
So, how can you achieve this goal?
Well, as it’s common in programming, you have to combine together some building blocks, and you get the solution to your problem.
A safe array can contain many different types, but the “natural” type for a Unicode string is BSTR. A BSTR is basically a length-prefixed Unicode string encoded using UTF-16.
ATL offers a convenient helper class to simplify safe array programming in C++: CComSafeArray. The MSDN Magazine article “Simplify Safe Array Programming in C++ with CComSafeArray” discusses with concrete sample code how to use this class. In particular, the paragraph “Producing a Safe Array of Strings” is the section of interest here.
So, this was the first building block. Now, let’s discuss the second.
You have a vector<string> as input. An important question to ask is what kind of encoding is used for the strings stored in the vector. It’s very common to store Unicode strings in std::string using the UTF-8 encoding. So, there’s an encoding impedance here: The input strings stored in the std::vector use UTF-8; but the output strings that will be stored as BSTR in the safe array use UTF-16. Ok, not a big problem: You just have to convert from UTF-8 to UTF-16. This is the other building block to solve the initial problem, and it’s discussed in the MSDN Magazine article “Unicode Encoding Conversions with STL Strings and Win32 APIs”.
So, to wrap up: You can go from a vector<string> to a safe array of BSTR strings following this path:
- Create a CComSafeArray<BSTR> of the same size of the input std::vector
- For each string in the input vector<string>, convert the UTF-8-encoded string to the corresponding UTF-16 wstring
- Create a CComBSTR from the previous wstring
- Invoke CComSafeArray::SetAt() to copy the CComBSTR into the safe array
The steps #1, #3, and #4 are discussed in the CComSafeArray MSDN article; the step #2 is discussed in the Unicode encoding conversion MSDN article.