函数原型:
/// <param name="pConvInfo">指向用来保存转换器列表的缓存</param>
/// <param name="count">为缓存中可保存多少个CONVINFO结构。</param>
/// <param name="bEnableMsg">在搜索的时候是否允许处理窗口消息。</param>
/// <param name="timeout">超时时间,单位为毫秒。</param>
/// <returns>搜索到的转换器的数目</returns>
 int _stdcall  FindConverter(CONVINFO *pConvInfo,int count,BOOL bEnableMsg,DWORD timeout);
c#函数申明:
[DllImport("Setting.dll",CharSet = CharSet.Ansi)]
internal unsafe static extern int FindConverter(_CONVINFO[] pConvInfo, int count, bool bEnableMsg,    uint timeout);
        [StructLayout(LayoutKind.Sequential)]
        public struct _CONVINFO
        {
            public ushort devType;     
            [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]            
            public string strIP;
            [MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
            public string strMAC;     
        }
c#调用:
    _CONVINFO[] Buffer = new _CONVINFO[256];
    int ILen = FindConverter(Buffer, 256, true, 3000);  
  函数调用后,Buffer里面没有数据返回。怎么回事?

解决方案 »

  1.   

    没有指定封送!为用户定义的结构指定自定义封送处理
    可以为传递到非托管函数或从非托管函数返回的结构和类的字段指定自定义封送处理属性。通过向结构或类的字段中添加 MarshalAs属性可以做到这一点。还必须使用 StructLayout 属性设置结构的布局,还可以控制字符串成员的默认封送处理,并设置默认封装大小。
    示例 3
    本示例说明如何为结构指定自定义封送处理属性。
    请考虑下面的 C 结构:
    typedef struct tagLOGFONT 

       LONG lfHeight; 
       LONG lfWidth; 
       LONG lfEscapement; 
       LONG lfOrientation; 
       LONG lfWeight; 
       BYTE lfItalic; 
       BYTE lfUnderline; 
       BYTE lfStrikeOut; 
       BYTE lfCharSet; 
       BYTE lfOutPrecision; 
       BYTE lfClipPrecision; 
       BYTE lfQuality; 
       BYTE lfPitchAndFamily; 
       TCHAR lfFaceName[LF_FACESIZE]; 
    } LOGFONT; 在 C# 中,可以使用 StructLayout 和 MarshalAs 属性描述前面的结构,如下所示:
    // logfont.cs
    // compile with: /target:module
    using System;
    using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential)]
    public class LOGFONT 

        public const int LF_FACESIZE = 32;
        public int lfHeight; 
        public int lfWidth; 
        public int lfEscapement; 
        public int lfOrientation; 
        public int lfWeight; 
        public byte lfItalic; 
        public byte lfUnderline; 
        public byte lfStrikeOut; 
        public byte lfCharSet; 
        public byte lfOutPrecision; 
        public byte lfClipPrecision; 
        public byte lfQuality; 
        public byte lfPitchAndFamily;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
        public string lfFaceName; 
    }
    有关 StructLayout 属性的语法的更多信息,请参见 StructLayoutAttribute 类。
    然后即可将该结构用在 C# 代码中,如下所示:// pinvoke.cs
    // compile with: /addmodule:logfont.netmodule
    using System;
    using System.Runtime.InteropServices;
     
    class PlatformInvokeTest
    {   
          [DllImport("gdi32.dll", CharSet=CharSet.Auto)]
          public static extern IntPtr CreateFontIndirect(
                [In, MarshalAs(UnmanagedType.LPStruct)]
                LOGFONT lplf   // characteristics
                );
     
          [DllImport("gdi32.dll")]
          public static extern bool DeleteObject(
                IntPtr handle
                );
     
          public static void Main() 
          {
                LOGFONT lf = new LOGFONT();
                lf.lfHeight = 9;
                lf.lfFaceName = "Arial";
                IntPtr handle = CreateFontIndirect(lf);
     
                if (IntPtr.Zero == handle)
                {
                      Console.WriteLine("Can't creates a logical font.");
                }
                else
                {            
                      if (IntPtr.Size == 4)
                            Console.WriteLine("{0:X}", handle.ToInt32());
                      else
                            Console.WriteLine("{0:X}", handle.ToInt64());                           // Delete the logical font created.
                      if (!DeleteObject(handle))
                           Console.WriteLine("Can't delete the logical font");
                }
          }
    }
    运行示例
    C30A0AE5
    代码讨论
    在前面的示例中,CreateFontIndirect 方法使用了一个 LOGFONT 类型的参数。MarshalAs 和 In 属性用于限定此参数。程序将由此方法返回的数值显示为十六进制大写字符串。
      

  2.   

    你不能直接定义FindConverter(_CONVINFO[]   pConvInfo,   int   count,   bool   bEnableMsg,         uint   timeout)这个函数
    在C#里把_CONVINFO[]   pConvInfo,改成int32 pConvInfo
    因为函数其实是传的指针,这样pConvInfo里得到的是这个内存块的地址指针再用C#里的Marshal.Copy或是Marshal.PtrToStructure把这个指针指的内存所在的内容COPY到你的Buffer里去
      

  3.   

    函数原型: 
    ///   <param   name= "pConvInfo "> 指向用来保存转换器列表的缓存 </param> 
    ///   <param   name= "count "> 为缓存中可保存多少个CONVINFO结构。 </param> 
    ///   <param   name= "bEnableMsg "> 在搜索的时候是否允许处理窗口消息。 </param> 
    ///   <param   name= "timeout "> 超时时间,单位为毫秒。 </param> 
    ///   <returns> 搜索到的转换器的数目 </returns> 
      int   _stdcall     FindConverter(CONVINFO   *pConvInfo,int   count,BOOL   bEnableMsg,DWORD   timeout); 
    c#函数申明: 
    [DllImport( "Setting.dll ",CharSet   =   CharSet.Ansi)] 
    internal   unsafe   static   extern   int   FindConverter(_CONVINFO[]   pConvInfo,   int   count,   bool   bEnableMsg,         uint   timeout); 
                    [StructLayout(LayoutKind.Sequential)] 
                    public   struct   _CONVINFO 
                    { 
                            public   ushort   devType;         
                            [MarshalAs(UnmanagedType.ByValTStr,   SizeConst   =   20)]                         
                            public   string   strIP; 
                            [MarshalAs(UnmanagedType.ByValTStr,   SizeConst   =   20)] 
                            public   string   strMAC;         
                    } 
    c#调用: 
            _CONVINFO[]   Buffer   =   new   _CONVINFO[256]; 
            int   ILen   =   FindConverter(Buffer,   256,   true,   3000);     
        函数调用后,Buffer里面没有数据返回。
      

  4.   


    public   struct  CONVINFO 
          { 
           MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)]                         
            public   ushort   devType;         
           
           [MarshalAs(UnmanagedType.LPStr,   SizeConst   =  20)]                         
            public   string   strIP; 
           
            [MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)] 
             public   string   strMAC;         
        }  CONVINFO con = new CONVINFO();
     [DllImport("gdi32.dll"]
      public static extern int FindConverter(ref con,int count,bool bEnableMsg,uint timeout);
    最好把C++的结构贴出来。
      

  5.   

    如果改为
    c#调用:  
      _CONVINFO Buffer = new _CONVINFO();  
      int ILen = FindConverter(ref Buffer, 1, true, 3000);  
    原型改为:
    [DllImport( "Setting.dll ",CharSet = CharSet.Ansi)]  
    internal unsafe static extern int FindConverter(ref _CONVINFO pConvInfo, int count, bool bEnableMsg, uint timeout);  能够返回,Buffer有值,但是需要返回多个值。
      

  6.   

      typedef struct _CONVINFO
    {
    char strMAC[20];
    char strIP[20];
    WORD devType;
    }CONVINFO;
     
    LOVESONGFOREVER 谢谢,但只能返回一个值
      

  7.   

    [DllImport( "Setting.dll ",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]  
    internal unsafe static extern int FindConverter(ref _CONVINFO[] pConvInfo, int count, bool bEnableMsg, uint timeout);
    int ILen = FindConverter(ref Buffer, 256, true, 3000);
    试试看行不
      

  8.   

    注意指针参数对应到C#的ref引用参数
      

  9.   

    Buffer是一个结构,他的属性就是你要的值。
      

  10.   


    public struct CONVINFO
    {
        MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)]
        public byte[] strMAC;
        
        MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)]
        public byte[] strIP;
      
        MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)]
        int devType;
      

  11.   

      无法封送处理类型为“_CONVINFO”的字段“strIP”: 无效的托管/非托管类型组合(数组字段必须与 ByValArray 或 SafeArray 成对出现)。不行
      

  12.   

    把string 换成substring 试一下
      

  13.   

    [DllImport( "Setting.dll ",CharSet   =   CharSet.Ansi)] 
    internal   unsafe   static   extern   int   FindConverter(int32   pConvInfo,   int   count,   bool   bEnableMsg,         uint   timeout); 
                    [StructLayout(LayoutKind.Sequential)] 
                    public   struct   _CONVINFO 
                    { 
                            public   ushort   devType;         
                            [MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)]                         
                            public   string   strIP; 
                            [MarshalAs(UnmanagedType.LPStr,   SizeConst   =   20)] 
                            public   string   strMAC;         
                    } int32 pBuffer;
    int   ILen   =   FindConverter(pBuffer,   256,   true,   3000);
    IntPtr pb = (IntPtr)pBuffer;
    for   (int   i   =   0;   i   <   ILen;   ++i) 
                            { 
                                    //extract   struct   from   pointer 
                                    _CONVINFO q   =   (_CONVINFO)Marshal.PtrToStructure(pb,   typeof(_CONVINFO)); 
    //让指针指到下一个,一直这样循环
                                    pb   =   (IntPtr)(pb.ToInt32()   +   Marshal.SizeOf(typeof(_CONVINFO))); 
                            } 
      

  14.   


    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public string strIP;结构这样封装;
      

  15.   

    C原型
    typedef struct _CONVSETTING
    {
    NETSETTING netSetting;
    SOCKSETTING sockSetting[8];
    COMSETTING comSetting[8];
    }C#中申明怎么定义
      [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct _CONVSETTING
            {
                public _NETSETTING netSetting;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
                public _SOCKSETTING[] sockSetting;
                [MarshalAs(UnmanagedType.LPStruct, SizeConst = 8)]
                public _COMSETTING[] comSetting;
            }
    调用时提示:
    类型“PbcClass.NetModelMethod+_CONVSETTING”不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。
      

  16.   


    C原型
    typedef struct _CONVSETTING
    {
    NETSETTING netSetting;
    SOCKSETTING sockSetting[8];
    COMSETTING comSetting[8];
    }C#中申明怎么定义
      [StructLayout(LayoutKind.Sequential, Pack = 1)]
      public struct _CONVSETTING
      {
      public _NETSETTING netSetting;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
      public _SOCKSETTING[] sockSetting;
      [MarshalAs(UnmanagedType.LPStruct, SizeConst = 8)]
      public _COMSETTING[] comSetting;
      }这种类型怎么处理,解决马上送分.谢谢
      

  17.   

    可以参考一下这个:
    http://topic.csdn.net/u/20090106/10/cd130dad-4d61-4bad-bb97-5d786fee9b26.html
      

  18.   

    感谢 computerfox 提供的示例,将 LPStr 修改为 ByValTStr 运行通过。