Native Plugin Development - Passing arrays of Strings?

Hi all,

I’ve scoured google for this, but can’t find a good answer. We want a struct that looks like this to be passed into unity:

[StructLayout(LayoutKind.Sequential)]
public struct MyPluginInterop
{
int numOfThings;
[MarshalAs (UnmanagedType.LPStr)]
public string someData;
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)]
public string[ ] things;

}

And the C++ version is:

struct MyPluginInterop
{
int numOfThings;
char* someData;
char** things;
};

I can easily pass strings and ints, but an array of strings is a no go. I’ve spent some time in the C# marshalling docs, yet cannot discern if this is possible or not. I am using SizeParamIndex to tell C# that my array’s size is the numOfThings, and other metadata, but Unity just immediately crashes.

In the past I have been able to use structs within structs, and use Marshal.PtrToStructure() to create structs with the strings inside them. We are also thinking about using one string and a delimiter as an alternative.

Thanks in advance!

So many years later after your question, I figure out how to marshal an array of strings from C++ in C# safe code.
Post that answer to help others Unity3D colleagues.
I simplify my sample many as I could.

I am not sure which platforms working that approach yet. Tested only on Windows Editor
Unity version tested: 2019.1.14f1

Use Callbacks to send C# calls to C++ and return a result
The trick is to use IntPtr and cast pointers to strings.

C++

struct UserEffect
{
    const char* StringParams[4];
};

C#

[StructLayout(LayoutKind.Sequential, Size = 32)]
public struct Params
{
    // ByValArray is the right way to call String array. LPArray doesn't work
   // SizeConst is the length of the array.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public IntPtr[] StringParams;
}

C++ assign and send the data

p.Params[0] = "Parameter 1";
p.Params[1] = "Parameter 2";
p.Params[2] = "Parameter 3";
p.Params[3] = "Parameter 4";

SendParams(p);

C# get data from C++

private static void ExecuteRendering(Params p)
{
    Debug.Log(Marshal.PtrToStringAnsi(p.Params[0]));
    Debug.Log(Marshal.PtrToStringAnsi(p.Params[1]));
    Debug.Log(Marshal.PtrToStringAnsi(p.Params[2]));
    Debug.Log(Marshal.PtrToStringAnsi(p.Params[3]));
}