C++DLL里的一个函数:
HRESULT DSStream_EnumVideoCompressor(VideoCompressorInfo * pInfo, int * piVidCompNum)
得到系统中安装的视频压缩算法的信息。
pInfo:
指向一片预先分配的VideoCompressorInfo结构。如果为 NULL,piVidCompNum 将得到系统中安装的视频压缩算法的数目。
piVidCompNum:
如果 pInfo 不为 NULL,piVidCompNum 表示 pInfo 中包含多少个 VideoCompressorInfo 结构。如果 pInfo 等于 NULL,piVidCompNum 返回系统中安装的视频压缩算法的数目。C#对该函数的封装:
class XNStream
{
        /// <summary>
        /// 视频压缩算法的信息结构体
         /// </summary>     
        [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]   
        public struct VideoCompressorInfo
        {
           [MarshalAs(UnmanagedType.ByValArray, SizeConst =256)]   
           public  char[] szName;
           public Int32 dwHandle;
        } 
 [DllImport("DSStream.dll")]        
  public static extern int DSStream_EnumVideoCompressor(VideoCompressorInfo[] pInfo, ref int piVidCompNum);
}
C#主类中的调用:
static void Main()
        {
            XNStream.VideoCompressorInfo[] pInfo;
            int num=0;
            int Result = XNStream.DSStream_EnumVideoCompressor(null, ref num);
            if (Result == 0 && num > 0)
            {
                pInfo=new XNStream.VideoCompressorInfo[num];
                Result = XNStream.DSStream_EnumVideoCompressor(pInfo, ref num);
                if (Result == 0)
                {
                    StringBuilder s = new StringBuilder();
                    for (int i = num - 1; i >= 0; i--)
                    {
                        s.Append(pInfo[i].szName);
                    }
                    MessageBox.Show(s.ToString());
                }
            }
        }
运行后得到的是空值,百度一下觉得是结构体在平台调用中出了问题,请同志们帮帮忙解决一下!谢谢

解决方案 »

  1.   

    看了下觉得有好几个地方都有问题:
    1.首先在结构体的定义上:
                          [MarshalAs(UnmanagedType.ByValArray,   SizeConst   =256)]       
                          public     char[]   szName; 
    szName最好改为StringBuilder类型.
    2.函数的第二次调用时是也有也有问题,在调用前应该先给szName分配空间:
    for(int i=0;i<num;++i) 
       pInfo[i].sizeName = new StringBuilder(256);
    3.可能这样还不能调用成功,可以试一下下面的方法:
    函数定义改为: [DllImport("DSStream.dll")]                 
        public   static   extern   int   DSStream_EnumVideoCompressor(IntPtr   pInfo,   ref   int   piVidCompNum); 调用时:           // 得到结构体的大小
                int size = Marshal.SizeOf(typeof(VideoCompressorInfo));
               // 分配结内存空间
               IntPtr structPtr = Marshal.AllocHGlobal(size*num);
               Result   =   XNStream.DSStream_EnumVideoCompressor(structPtr,   ref   num); 
               pInfo=new   XNStream.VideoCompressorInfo[num]; 
               for(int i=0;i<num;++i)
                   pInfo[i] =  Marshal.PtrToStructure(structPtr+i*size, typeof(VideoCompressorInfo));
               Marshal.FreeHGlobal(structPtr);
     
    随手敲的可能会有错,过关结构体可以看一下我的blog的一篇文章:C#通过TCP传送结构体           
      

  2.   

    TO: Whislly 
    用了你的方法,修改后的代码如下:
            [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]   
            public  struct VideoCompressorInfo
            {
               [MarshalAs(UnmanagedType.ByValArray, SizeConst =256)]
               public StringBuilder szName;
               public Int32 dwHandle;
            } 
    //------------------------------------------------
     [DllImport("DSStream.dll")]
            public static extern int DSStream_EnumVideoCompressor(IntPtr pInfo, ref int piVidCompNum);
    //-----------------------------------------------调用代码:
     XNStream.VideoCompressorInfo[] pInfo;
                int num=0;
                int Result = XNStream.DSStream_EnumVideoCompressor(IntPtr.Zero, ref num);
                if (Result == 0 && num > 0)
                {
                    for (int i = 0; i < num; ++i)
                    {
                        pInfo[i].szName = new StringBuilder(256);
                    }
                    int size = Marshal.SizeOf(typeof(XNStream.VideoCompressorInfo));
                    IntPtr structPtr = Marshal.AllocHGlobal(size * num);
                    Result = XNStream.DSStream_EnumVideoCompressor(structPtr, ref num);
                    if (Result == 0)
                    {
                        pInfo = new XNStream.VideoCompressorInfo[num];
                        for (int i = 0; i < num; ++i)
                            pInfo[i] = Marshal.PtrToStructure(structPtr + i * size, typeof(XNStream.VideoCompressorInfo));//出错点,第一个参数:运算符+无法应用于IntPtr和int类型的操作数
                        Marshal.FreeHGlobal(structPtr);
                        StringBuilder s = new StringBuilder();
                        for (int i = 0; i < pInfo.Length; i++)
                        {
                            s.Append(pInfo[i].szName.ToString()+"\n");
                        }
                        MessageBox.Show(s.ToString());
                    }
                }
    希望你能继续帮我解决,谢谢!
      

  3.   

    Marshal.PtrToStructure((IntPtr)((int)structPtr+ i*size),   typeof(XNStream.VideoCompressorInfo));
     改成这样再试试。
                                    for   (int   i   =   0;   i   <   num;   ++i) 
                                    { 
                                            pInfo[i].szName   =   new   StringBuilder(256); 
                                    } 
    这一段可以不用,不然会出错。
      

  4.   


        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct VideoCompressorInfo
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string szName;
            public Int32 dwHandle;
        }        [DllImport("DSStream.dll")]
            public extern static int DSStream_EnumVideoCompressor(IntPtr pInfo, ref int piVidCompNum);             int num = 0;            DSStream_EnumVideoCompressor(IntPtr.Zero, ref num);            int size = Marshal.SizeOf(typeof(VideoCompressorInfo));            IntPtr structPtr = Marshal.AllocHGlobal(size * num);            DSStream_EnumVideoCompressor(structPtr, ref num);            VideoCompressorInfo[] infos = new VideoCompressorInfo[num];            for (int i = 0; i < num; ++i)
                {
                    infos[i] = (VideoCompressorInfo)Marshal.PtrToStructure((IntPtr)((int)structPtr + i * size), typeof(VideoCompressorInfo));
                }            Marshal.FreeHGlobal(structPtr);  这样应该就可以了,我自己写了个C++的DLL模拟DSStream_EnumVideoCompressor函数,测试通过。
      

  5.   

    TO “Whislly”:老大,你太牛X了!很感谢你的帮助。谢谢了