views:

569

answers:

2

I am having some trouble settling on a way to represent a structure that contains a pointer to an array of shorts in my managed code. The struct looks like this:

typedef struct
{
    short size;
    unsigned short** shortValues;
} UnmanagedStruct;

memory for 'shortValues' is allocated inside unmanaged code -- therefore even though that field is simply a pointer to an array of short values, an additional level of indirection was added so that allocated memory is seen by the caller (managed code) too. The 'size' field represents the number of elements in the array. How do I represent this in managed code?

I thought I'd pass it in just an IntPtr, then I couldn't figure out how to access the values once the unmanaged call returns.

A: 

Is unsafe code ok?

public unsafe struct UnmanagedStruct
{
    public short size;
    public ushort** shortValues;
}

[DllImport("example.dll")]
public static extern void GetUnmanagedStruct(out UnmanagedStruct s);

If you have a pointer to an array of ushorts:

public static unsafe void WriteValues()
{
    UnmanagedStruct s;
    GetUnmanagedStruct(out s);
    for (var i = 0; i < s.size; i++)
    {
        ushort x = (*s.shortValues)[i];
        Console.WriteLine(x);
    }
}

If you have an array of null-terminated arrays of ushorts:

public static unsafe void WriteValues()
{
    UnmanagedStruct s;
    GetUnmanagedStruct(out s);
    for (var i = 0; i < s.size; i++)
    {
        for (ushort* p = s.shortValues[i]; p != null; p++)
        {
            ushort x = *p;
            Console.WriteLine(x);
        }
    }
}
dtb
That code looks exactly right to me. Thanks dtb! While I have your attention, can I ask one other question? I have posted it in another thread:http://stackoverflow.com/questions/1323797/marshaling-pointer-to-an-array-of-strings
Dilip
BTW: it's better to update your question than to post an answer to your question with new details. Also, if an answer solves a your problem, don't forget to accept it! :)
dtb
@dtb: I must be blind here but how do I "accept" an answer?
Dilip
@Dilip: click the checkmark next to an answer
dtb
A: 

Sorry guys.. I got the problem statement wrong. It looks like:

unsigned short** shortValues;

is a pointer to array of pointer to shorts. So each element is itself a short*

The only way I can think of doing this is:

public class UnmanagedStruct { public int size; public IntPtr shortValues; }

After the call returns from unmanaged code:

IntPtr[] listOfShorts = new IntPtr[size]; Marshal.Copy(shortValues, listOfShorts, 0, size);

Each IntPtr in listOfShorts now points to a short[]. But now the problem is I don't know the size of each individual array which means I can't extract them.

I have to be missing some key piece of information somewhere.

Dilip