How do you marshal an array as a return value What marshalling attributes must be specified
Specifically, using COM Interop, I want to use an interface member that returns an array. The implementation of this interface is written using an unmanaged object and a COM style interface.
In C#, the interface declaration would look like this:
public interface IMyInterface
{
int[] MyArray
{
get;
}
}
In unmanaged COM interface land, the property get function looks like this:
struct IMyInterface : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE get_MyArray( int** array, int* size );
// array is an "out" parameter, a pointer to an array of integers
// size is an "out" parameter, and returns the number of elements in the array.
};
How do I provide marshalling attributes on the MyArray property get declaration such that I can call this function
If it's not directly possible, then I am willing to make some compromises:
1) I'm prepared to accept a method declaration in the c# interface declaration, rather than a property get. Like this:
int[] MyArray();
2) I'm prepared to rewrite the implementation of the get_MyArray unmanaged function
3) I'm prepared to modify the signature of the unmanaged function. For example, I'm okay if it has to look like this:
virtual HRESULT STDMETHODCALLTYPE get_MyArray( int* size, SOMETHING<SOMETHINGELSE>* array );
3) I'm prepared to allocate the array in the implementation using CoTaskMemAlloc or whatever memory allocation necessary.
Some details on which I am NOT willing to compromise:
1) The array must be a return value in C#. I am NOT prepared to change the IMyInterface method to this:
void MyArray( out int[] array, out int size );
2) I do not want to take additional marshalling steps in the caller. So I don't want to have to call:
Marshal.FreeCoTaskMem()
3) The size of the array must be variable, in that it must not a constant size in the marshalling attributes. The returned array, could contain any number of elements.
Here's something I tried that did not work:
public interface IMyInterface
{
int[] MyArray
{
[ return : MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1) ]
get;
}
}
I get the following error:
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in Test.exe
Additional information: Can not marshal return value.

Marshaling an array as a return value?
ducksauce
>3) I'm prepared to modify the signature of the unmanaged function.
Great, then try something like this (in IDL to highlight the attributes and SAFEARRAY element type):
HRESULT get_MyArray([out,retval] SAFEARRAY(int) *array);
Since SAREARRAYs are selfdescribing you don't need the size parameter.
mahesh kuhikar
SAFEARRAY is the Automation array type which carries type, rank and bounds with it. It's all documented here
http://msdn.microsoft.com/library/en-us/automat/html/28a00e34-3b5e-4a16-9f4c-dd2a72dc8e46.asp
I guess the C++ signature becomes
virtual HRESULT STDMETHODCALLTYPE get_MyArray(SAFEARRAY** array);
It's declared in Oaidl.h but you typically include Oleauto.h.
SS38
I have to admit, I have no idea what SAFEARRAY is or where it's declared or anything. I'm not using MFC, or ATL, or anything like that. I'm not using the MIDL compiler. I have no .idl files. I don't have a type library.
It's a roll-your-own implementation. All I did is derive my object from an interface class that I made that inherits from IUnknown.
Could you explain SAFEARRAY please