none
C#调用DLL问题 RRS feed

  • 问题

  • 请各位大牛帮帮忙,C#调用DLL时,DLL函数返回的是结构体指针,该怎么声明和接收这个指针呢?
    2010年10月30日 15:47

答案

  • 这个比较简单:

    1) 按照DLL 定义的那个结构体,用C# 声明一个一样的结构体

    2) 传递参数时,用IntPtr 这个类型

    3) 用 Marshal.PtrToStructure() 转换指针对象成为结构体

    典型的如:
    Status GdiplusStartup(          ULONG_PTR token *token,
        const GdiplusStartupInput *input,
        GdiplusStartupOutput *output
    );

    C# 的P/Invoke 声明为:
    [DllImport("gdiplus.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
    static extern int GdiplusStartup(out IntPtr token, ref StartupInput input,
    out  StartupOutput output);

    你也可以直接将一个结构体的引用作为参数传递,.NET 的互操作模块会自动帮你做Marshal
    比如这个函数:
    DWORD WINAPI CredUIPromptForCredentials(
      __in_opt      PCREDUI_INFO pUiInfo,
      __in          PCTSTR pszTargetName,
      __in          PCtxtHandle Reserved,
      __in_opt      DWORD dwAuthError,
      __in_out      PCTSTR pszUserName,
      __in          ULONG ulUserNameMaxChars,
      __in_out      PCTSTR pszPassword,
      __in          ULONG ulPasswordMaxChars,
      __in_out      PBOOL pfSave,
      __in          DWORD dwFlags
    );

    C# P/Invoke 声明为:
    [DllImport("credui", CharSet = CharSet.Unicode)]
      private static extern CredUIReturnCodes CredUIPromptForCredentialsW(ref CREDUI_INFO creditUR,
                string targetName,
                IntPtr reserved1,
                int iError,
                StringBuilder userName,
                int maxUserName,
                StringBuilder password,
                int maxPassword,
                [MarshalAs(UnmanagedType.Bool)] ref bool pfSave,
                CREDUI_FLAGS flags);


    我想你最需要的还是这个网站www.pinvoke.net 在这个网站上绝大多数的Window API 的P/Invoke 声明都可以查到。


    Would you know my name, if I saw you in heaven......
    2010年11月1日 4:24

全部回复

  • 请问各位大牛,C#调用DLL时的参数传递msdn讲的很清楚了,可是当dll函数返回结构体指针时该怎么处理呢?急等!!!!谢谢
    2010年10月30日 15:39
  • 这个比较简单:

    1) 按照DLL 定义的那个结构体,用C# 声明一个一样的结构体

    2) 传递参数时,用IntPtr 这个类型

    3) 用 Marshal.PtrToStructure() 转换指针对象成为结构体

    典型的如:
    Status GdiplusStartup(          ULONG_PTR token *token,
        const GdiplusStartupInput *input,
        GdiplusStartupOutput *output
    );

    C# 的P/Invoke 声明为:
    [DllImport("gdiplus.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
    static extern int GdiplusStartup(out IntPtr token, ref StartupInput input,
    out  StartupOutput output);

    你也可以直接将一个结构体的引用作为参数传递,.NET 的互操作模块会自动帮你做Marshal
    比如这个函数:
    DWORD WINAPI CredUIPromptForCredentials(
      __in_opt      PCREDUI_INFO pUiInfo,
      __in          PCTSTR pszTargetName,
      __in          PCtxtHandle Reserved,
      __in_opt      DWORD dwAuthError,
      __in_out      PCTSTR pszUserName,
      __in          ULONG ulUserNameMaxChars,
      __in_out      PCTSTR pszPassword,
      __in          ULONG ulPasswordMaxChars,
      __in_out      PBOOL pfSave,
      __in          DWORD dwFlags
    );

    C# P/Invoke 声明为:
    [DllImport("credui", CharSet = CharSet.Unicode)]
      private static extern CredUIReturnCodes CredUIPromptForCredentialsW(ref CREDUI_INFO creditUR,
                string targetName,
                IntPtr reserved1,
                int iError,
                StringBuilder userName,
                int maxUserName,
                StringBuilder password,
                int maxPassword,
                [MarshalAs(UnmanagedType.Bool)] ref bool pfSave,
                CREDUI_FLAGS flags);


    我想你最需要的还是这个网站www.pinvoke.net 在这个网站上绝大多数的Window API 的P/Invoke 声明都可以查到。


    Would you know my name, if I saw you in heaven......
    2010年11月1日 4:24
  • Thank you for your information in detail,thank you again!
    银国徽
    2010年11月1日 12:49