marshalling safearray RRS feed

  • Question

  • Hi, i'm trying to return a SafeArray<BSTR> from a unmanaged dll to managed .net code.
    I don't know the size of the array, so i can't pass it as argument and just fill it in the unmanaged code. In the example the SafeArray is constructed with fixed size but int real life it would be dynamically assign.
    C :
    SAFEARRAY * return_safe_array(void)
    		HRESULT hr = S_OK;
    		// safe array dim
    		SAFEARRAYBOUND safeArrayDim[1];
    		safeArrayDim[0].lLbound = 0;
    		safeArrayDim[0].cElements = 5;
    		// create safe array
    		SAFEARRAY * pSafeArray = SafeArrayCreate(VT_BSTR,1,safeArrayDim);
    		if(pSafeArray != NULL) {
    			unsigned int i;
    			long index;
    			for(i = safeArrayDim[0].lLbound; i < safeArrayDim[0].cElements + safeArrayDim[0].lLbound; i++) {
    				index = i;
    				BSTR data = ::SysAllocString(A2W("this is a test"));
    				hr = SafeArrayPutElement(pSafeArray, &index, data);
    				if(hr != S_OK) {
    					return NULL;
    		return pSafeArray;
    [DllImport("C:\\path\\to\\library\\library.dll", EntryPoint = "return_safe_array")]
            public static extern string [] return_safe_array();
            static void Main(string[] args)

    and i get this exception:
    Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException: C
    annot marshal 'return value': Invalid managed/unmanaged type combination.

    what i am getting wrong ? thanks
    Thursday, October 1, 2009 2:59 PM


  • Make it look like this:

        [return: MarshalAs(UnmanagedType.SafeArray)]
        private static extern string[] return_safe_array();

    Your C/C++ function ought to look like this:

    extern "C" __declspec(dllexport)
    SAFEARRAY* __stdcall return_safe_array(void)

    Hans Passant.
    Thursday, October 1, 2009 7:48 PM