Andrew - I hve to ge this back up. Found the time to try it out today,
but it breaks.

This is the interface I have now (part of, only):

        public interface IEnumPins {

                int Next(
                        [In] int cPins, 
                        [In, Out] ref IntPtr ppPins, out int pcFetched);

And this is my code- basically a copy of your code trying to get the
first 32 pins.

                public static IPin [] GetPins (IBaseFilter Filter) {
                        int size = 32;
                        IntPtr pPinArrayUM = IntPtr.Zero;
                        int fetched = 0;
                        IPin [] pins = new IPin [0];

                        IEnumPins pinEnum = null;
                        try {
                                int ptrsize =
Marshal.SizeOf(typeof(IntPtr));
                                pPinArrayUM = Marshal.AllocCoTaskMem
(size * ptrsize);

                                Filter.EnumPins( out pinEnum );

                                pinEnum.Next (size, ref pPinArrayUM, out
fetched);
                                pins = new IPin [fetched];
                                for (int i = 0; i < fetched; i++) {
                                        IntPtr pPin = Marshal.ReadIntPtr
(pPinArrayUM, i*ptrsize);
                                        pins [i] = (IPin)
Marshal.GetObjectForIUnknown (pPin);
                                }
                        } finally {
                                if (pinEnum != null) {
                                        Marshal.ReleaseComObject
(pinEnum);
                                }
                                if (pPinArrayUM != IntPtr.Zero) {
                                        Marshal.FreeCoTaskMem
(pPinArrayUM);
                                }
                        }
                        return pins;
                }

I get the following erroneus behavior when single stepping:
(a) after calling the pinEnum.Next function, the debugger changes the
values shown for pPinArrayUM AND size - they change both their values to
something pretty high. Looks like the pointers are being overwritten.
(b) when continuing, the followng error happens at the first
GetObjectForIUnknown:
Unhandled Exception: System.NullReferenceException: Object reference not
set to an instance of an object.
   at System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(IntPtr
pUnk)
   at
ThonaConsulting.DirectShow.Utilities.FilterUtility.GetPins(IBaseFilter
Filter) in
c:\work\thonaconsulting\directshow\thonaconsulting.directshow\utilities\
filterutility.cs:line 31

This looks very much like the data is being written to the wrong areas
upon return. I am pretty sure it is a totally stupid error, but I dont
find it.

I just wish, interop would be more powerfull.

Thomas


-----Original Message-----
From: Andrew Hopper [mailto:Andy.Hopper@;MINDSPRING.COM] 
Sent: Montag, 14. Oktober 2002 16:37
To: [EMAIL PROTECTED]
Subject: Re: [ADVANCED-DOTNET] FW: Interop: Handling OUT parameter of
array, gets error "Can not use SizeParamIndex for byref array
parameters."??


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:ADVANCED-DOTNET@;DISCUSS.DEVELOP.COM] 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.

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