Hello, Thomas-

>From what I understand, using the SizeParamIndex to marshal arrays only
works for marshaling data from managed code into COM and will not work
for out parameters. Due to this, I'm afraid you won't be able to use the
default marshaling provided by the framework. However, you should still
be able to accomplish this task - it will simply require a little more
work on your part.

I would change the method declaration to be:
...
// Eliminate PreserveSig unless you need to interpret the HRESULT
/// <summary>
/// The Next method retrieves a specified number of pins in the
enumeration sequence
/// </summary>
/// <param name="cPins">Number of pins to retrieve</param>
/// <param name="ppPins">Array of size cPins that is filled with IPin
pointers</param>
/// <param name="pcFetched">Pointer to a variable that receives the
number of pins retrieved</param>void Next(
          // Pass the count we expect
          int cPins,
          // pass a pointer to a pointer that points to allocated memory
          ref IntPtr ppPins,
          // pass a pointer to an int that will be filled with the count
          out int pcFetched
          );
...

You would then have to wrap the method call in some helper code:
// I'm assuming you already have obtained a pointer to
// the IEnumPins interface and stored it in pEnum...
IEnumPins pEnum;
int numPins,
    cFetched,
    sizeOfIntPtr;
IntPtr pPinArray = IntPtr.Zero,
       pPin;
IPin[] arrayOfPins;

try
{
  // This is kind of anal - you could easily just use 4 instead of
calculating
  // the size...
  sizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));

  numPins = 42; //Put some real number here...
  // Allocate space to hold the array
  pPinArray = Marshal.AllocCoTaskMem[sizeOfIntPtr * numPins];
  // Fill the array
  pEnum.Next(numPins, ref pPinArray, out cFetched);
  // Allocate space to hold the array of interfaces
  arrayOfPins = new IPin[cFetched];
  // Load the array elements
  for(int counter = 0; counter < cFetched; counter++)
  {
    // nibble off an IntPtr at a time,
    // incrementing the offset as we go
    pPin = Marshal.ReadIntPtr(pPinArray, counter * sizeOfIntPtr);
    // convert the IntPtr to a managed pointer to an IPin
    arrayOfPins[counter] = (IPin)Marshal.GetObjectForIUnknown(pPin);
  }
}
finally
{
  if(pPinArray != IntPtr.Zero) Marshal.FreeCoTaskMem(pPinArray);
}

// Do something with the array
...

Hope this works (and helps)!
-Andy Hopper


-----Original Message-----
From: Moderated discussion of advanced .NET topics.
[mailto:[EMAIL PROTECTED]] On Behalf Of Thomas
Tomiczek
Sent: Monday, October 14, 2002 6:49 AM
To: [EMAIL PROTECTED]
Subject: [ADVANCED-DOTNET] FW: Interop: Handling OUT parameter of array,
gets error "Can not use SizeParamIndex for byref array parameters."??


> Hello, simple question (so to say).
>
> I ham trying to manage interoo for interface arrays.
>
> This interface definition is not working. It is for a DirectShow
> Interface:
>
>       [ComVisible(true), ComImport,
>       Guid("56a86892-0ad4-11ce-b03a-0020af0ba770"),
>       InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
>       public interface IEnumPins {
>               [PreserveSig]
>               int Next(
>                       [In] int cPins,
>                       [Out, MarshalAs(UnmanagedType.LPArray,
> SizeParamIndex=2)] out IPin[] ppPins,
>                       [Out] out int pcFetched );
>
>               [PreserveSig]
>               int Skip( [In] int cPins );
>               void Reset();
>               void Clone( [Out] out IEnumPins ppEnum );
>       }
>
> When trying to use the next function, I get this error:
>
>       An unhandled exception of type
> 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in

> thonaconsulting.directshow.dll
>       Additional information: Can not use SizeParamIndex for byref
> array parameters.
>
> That is sad, because I stop having clues on how to get this out.
> Basically I try to get the next x pins. The 2nd parameter (index 1)
> returns an array to the pints taken, and the third parameter returns
> the number of pins put into the arrray.
>
> The error appears under .NET framework 1.1 - no way to check 1.0
> easly.
>
The stack trace shows that the error apears within the marshalling:

   at ThonaConsulting.DirectShow.IEnumPins.Next(Int32 cPins, IPin[]&
ppPins, Int32& pcFetched)
   at
ThonaConsulting.DirectShow.Utilities.FilterUtility.GetPin(IBaseFilter
Filter, PinDirection Direction) in
c:\work\thonaconsulting\directshow\thonaconsulting.directshow\utilities\
filterutility.cs:line 29

> Any clues?
>
> Thomas Tomiczek
> THONA Consulting Ltd.
> (Microsoft MVP C#/.NET)

You can read messages from the Advanced DOTNET archive, unsubscribe from
Advanced DOTNET, or subscribe to other DevelopMentor lists at
http://discuss.develop.com.

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to