How to return array of structs from unmanaged DLL to C#?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?RGFya3Jpc2Vy?=

    How to return array of structs from unmanaged DLL to C#?

    Mates,
    the problem is pretty simple, but I'm unable to manage it... Therefore
    asking you for help.

    Situation:
    Have managed code in C# and unamanged code in C++ DLL.
    I need to make a call from C# to a function exported by the DLL.
    Moreover, I have following struct (in C# and C++, as well):
    struct myStruct {
    unsigned int val1;
    unsigned int val2;
    }

    What I need:
    The C# function declares two empty variables (one for the array itself and
    second one for the number of items returned in the array) and passes them
    using "ref" keyword to C++ function. The C++ function determines the number
    of array elements that will be returned, dynamically allocates memory,
    creates the array of structs and passes it (along with the size of the array
    itself) to the C# function.

    Assumptions:
    - C# code (the calling one) doesn't know the number of items in the array
    that will be returned
    - C# must NOT use unsafe code
    - the number of items in the array may vary, but will always be >0

    I know that Marshalling/Serialization will be required, but I can't find the
    right code. Below, you can see my current C++ and C# code. I'm able to return
    and marshal only 1 element. Any ideas?

    // C++ code - currently returns only 1 element
    struct test {
    unsigned int val1;
    unsigned int val2;
    };

    extern "C" __declspec(dlle xport) void Test(test** pArray, int* pSize)
    {
    *pArray = (test*) CoTaskMemAlloc( sizeof(test) * 1);
    for (unsigned int i = 0; i < 1; i++)
    {
    (*pArray + i)->accountID = i;
    (*pArray + i)->period = i+1;
    (*pArray + i)->cycle = i+2;
    (*pArray + i)->cellType = i+3;
    }
    *pSize = 1;
    }

    // C# code
    [StructLayout(La youtKind.Sequen tial)]
    public class clTest
    {
    public uint val1;
    public uint val2;
    }

    [DllImport("some dll.dll")]
    public static extern void Test(out IntPtr tst, ref int pSize);

    IntPtr buffer;
    int size = 0;

    Test(out buffer, ref size);
    if (size 0)
    {
    clTest arr = new clTest();
    Marshal.PtrToSt ructure(buffer, arr );
    Marshal.FreeCoT askMem(buffer);
    }
  • =?Utf-8?B?RGFya3Jpc2Vy?=

    #2
    RE: How to return array of structs from unmanaged DLL to C#?

    pls, anyone?

    "Darkriser" wrote:
    Mates,
    the problem is pretty simple, but I'm unable to manage it... Therefore
    asking you for help.
    >
    Situation:
    Have managed code in C# and unamanged code in C++ DLL.
    I need to make a call from C# to a function exported by the DLL.
    Moreover, I have following struct (in C# and C++, as well):
    struct myStruct {
    unsigned int val1;
    unsigned int val2;
    }
    >
    What I need:
    The C# function declares two empty variables (one for the array itself and
    second one for the number of items returned in the array) and passes them
    using "ref" keyword to C++ function. The C++ function determines the number
    of array elements that will be returned, dynamically allocates memory,
    creates the array of structs and passes it (along with the size of the array
    itself) to the C# function.
    >
    Assumptions:
    - C# code (the calling one) doesn't know the number of items in the array
    that will be returned
    - C# must NOT use unsafe code
    - the number of items in the array may vary, but will always be >0
    >
    I know that Marshalling/Serialization will be required, but I can't find the
    right code. Below, you can see my current C++ and C# code. I'm able to return
    and marshal only 1 element. Any ideas?
    >
    // C++ code - currently returns only 1 element
    struct test {
    unsigned int val1;
    unsigned int val2;
    };
    >
    extern "C" __declspec(dlle xport) void Test(test** pArray, int* pSize)
    {
    *pArray = (test*) CoTaskMemAlloc( sizeof(test) * 1);
    for (unsigned int i = 0; i < 1; i++)
    {
    (*pArray + i)->accountID = i;
    (*pArray + i)->period = i+1;
    (*pArray + i)->cycle = i+2;
    (*pArray + i)->cellType = i+3;
    }
    *pSize = 1;
    }
    >
    // C# code
    [StructLayout(La youtKind.Sequen tial)]
    public class clTest
    {
    public uint val1;
    public uint val2;
    }
    >
    [DllImport("some dll.dll")]
    public static extern void Test(out IntPtr tst, ref int pSize);
    >
    IntPtr buffer;
    int size = 0;
    >
    Test(out buffer, ref size);
    if (size 0)
    {
    clTest arr = new clTest();
    Marshal.PtrToSt ructure(buffer, arr );
    Marshal.FreeCoT askMem(buffer);
    }

    Comment

    Working...