none
c#调用DLL的回调函数与结构体问题 RRS feed

  • 问题

  • C++封装的结构体与函数形式如下:

    typedef struct _DS_INFO{
    DWORD apid;
    WORD hwid;
    WORD flag;
    DWORD real_ip_addr;
    DWORD pseudo_ip_addr;
    DWORD host_ip_addr;
    BYTE mac[MACLEN];
    }DS_INFO, *PDS_INFO;

    到处DLL:
    IMPORT_EXPORT int SDKCI_FUNC dsc_EnumSearch(DWORD server_ip, WNDENUMSEARCHPROC lpenumproc);

    typedef int (CALLBACK* WNDENUMSEARCHPROC)(PDS_INFO);


    我对应的C#转换调用形式如下:


     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
     public struct DS_INFO
      {
      public uint apid;
      public ushort hwid;
      public ushort flag;
      public uint real_ip_addr;
      public uint pseudo_ip_addr;
      public uint host_ip_addr;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
      public byte[] mac;
      }

     public delegate int ProcessDelegate(ref DS_INFO dsinfo);

    [DllImport(".\\NECI.dll",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]  
     unsafe public static extern int dsc_EnumSearch(uint server_ip, ProcessDelegate lpenumproc);

     int EnumSearchProc( ref DS_INFO dsinfo)
      {
      Trace.WriteLine("call back ");
      }

    程序调用部分:
    try
    {
     ProcessDelegate newCallproc = new ProcessDelegate(EnumSearchProc);
     int ret = dsc_EnumSearch(0xffffffff, newCallproc);
    }
    catch(Exception ex)
    {
      throw ex;//System.ArgumentNullException 中第一次偶然出现的“未知模块”类型的异常
    }
    /////////////////
    请问我上述封装有什么问题?DLL可以确定没有任何问题。有意帮忙调试的大侠,请留下EMAIL。
    2010年6月18日 14:14

答案

  • C++类型到C#类型映射出错

    1,

    BYTE mac[MACLEN];  MACLEN是否固定为6

    如果不是

    用System.IntPtr 

    2,

    public delegate int ProcessDelegate(ref DS_INFO dsinfo);

    改为 

    public delegate int ProcessDelegate(System.IntPtr dsinfo);

    之后用Marshal.PtrToStructure

    在回掉函数里将Ptr转换为对应的结构体或者结构体数组。

     

    • 已标记为答案 jinxuliang 2010年6月20日 2:48
    2010年6月19日 5:49

全部回复

  • 你好!

         把try...catch去掉,看看抛出什么异常?


    周雪峰
    2010年6月19日 0:18
    版主
  • 通过单步调试异常是下面这句话抛出的:

    int ret = dsc_EnumSearch(0xffffffff, newCallproc);

    去掉异常捕获错误信息描述如下:


    未处理的“System.ArgumentNullException”类型的异常出现在 未知模块 中。

    其他信息: 值不能为空。

    2010年6月19日 1:08
  • 你好!

         很可能是你传参数的问题,具体那个dll如何使用这样参数我不是很了解,你可以跟踪看看!另外,堆栈信息你查看一下,应该可以看出问题的源头!


    周雪峰
    2010年6月19日 1:30
    版主
  • C++类型到C#类型映射出错

    1,

    BYTE mac[MACLEN];  MACLEN是否固定为6

    如果不是

    用System.IntPtr 

    2,

    public delegate int ProcessDelegate(ref DS_INFO dsinfo);

    改为 

    public delegate int ProcessDelegate(System.IntPtr dsinfo);

    之后用Marshal.PtrToStructure

    在回掉函数里将Ptr转换为对应的结构体或者结构体数组。

     

    • 已标记为答案 jinxuliang 2010年6月20日 2:48
    2010年6月19日 5:49