Marshal a C char[][] array to C#

2019-05-03 05:09发布

问题:

I have looked and looked and tried everything I can think of or have found suggested. I'm still not having any luck getting the data I need.

I'm using a third party DLL, which I believe is written in C. I need to access the functions from this DLL in C#. For the most part, I have this working, except for one function. The function I'm having problems with has the following header:

uint queryNumOfServers(USHORT *NumOfServers, char ServerNames[8][16]);

I have the following declared in my C# application

[DllImport("client.dll", CharSet=CharSet.Ansi]
public static extern uint queryNumOfServers(ref short numberofServer, StringBuilder serverNames);

I call this as follows:

StringBuilder serverNames = new StringBuilder(128);
short numServers = -1;
queryNumberOfServers(ref numServers, serverNames);

The problem is, while numberOfServers come back equal to 4, I only get one name in serverNames. I have tested the above C function in a small C program. I get back numberOfServer = 4 but I also get 4 names back.


I have tried the following with no success:

[DllImport("client.dll", CharSet=charSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint queryNumOfServers(ref short numberOfServer,[MarshalAs(UnmanagedType.LPStr)] string serverNames);

Called this with

string serverNames = new string('\0', 128);
queryNumOfServers(ref numServers, serverNames);

There is no change to serverNames with this option.


The development environment is Visual Studio 2008.

回答1:

After much searching and hair pulling, this was the solution that worked for me.

Declared the function header in my C# application as:

[DllImport("client.dll", CharSet = CharSet.Ansi)]
public static extern uint queryNumOfServers(ref short numberOfServers, [MarshalAs(UnmanagedType.LPArray)] byte[,] serverNames);

Then called as follows:

byte[,] serverNames = new byte[8,16];
short numServers = -1;
queryNumberOfServers(ref numServers, serverNames);

This returns a double index byte array. From here I used Buffer.BlockCopy() and Encoding.UTF8.GetString() to convert my byte array into a array of strings.



回答2:

I would use [StructLayout(LayoutKind.Sequential...] and [MarshalAs(UnmanagedType.ByValTStr...].

Here are two good examples:

Marshalling a C 2-Dimensional fixed length char array

Marshaling a C++ two-dimensional fixed length char array as a structure member