• C# COM 调用C++编写的DLL函数各种参数传递问题


    这两天一直在试着调用C++编写的Dll动态链接库来实现一些功能,初学总是遇见各种各样的问题,这次要实现一个改变系统时间的小功能,从而找到SetSystemTime这个系统API,
    SetSystemTime的原型为:
     1 BOOL WINAPI SetSystemTime(
     2   _In_  const SYSTEMTIME *lpSystemTime
     3 );
     4 
     5 typedef struct _SYSTEMTIME {
     6   WORD wYear;
     7   WORD wMonth;
     8   WORD wDayOfWeek;
     9   WORD wDay;
    10   WORD wHour;
    11   WORD wMinute;
    12   WORD wSecond;
    13   WORD wMilliseconds;
    14 } SYSTEMTIME;
    View Code

    C# 实现
     1 [StructLayout(LayoutKind.Sequential)]
     2 public struct SYSTEMTIME
     3 {
     4    public short wYear;
     5    public short wMonth;
     6    public short wDayOfWeek;
     7    public short wDay;
     8    public short wHour;
     9    public short wMinute;
    10    public short wSecond;
    11    public short wMilliseconds;
    12 }
    13 // top of class:
    14 [DllImport("kernel32.dll", SetLastError = true)]
    15 public static extern bool SetSystemTime(ref SYSTEMTIME theDateTime);
    16 //..
    17 //..
    18 private bool DoSetSystemTime(DateTime newTime)
    19 {   
    20    SYSTEMTIME st = new SYSTEMTIME();
    21    st.wDay = (short)newTime.Now.Day;
    22    st.wDayOfWeek = (short)newTime.Now.DayOfWeek;
    23    st.wHour = (short)newTime.Now.Hour;
    24    st.wMilliseconds = (short)newTime.Now.Millisecond;
    25    st.wMinute = (short)newTime.Now.Minute;
    26    st.wMonth = (short)newTime.Now.Month;
    27    st.wSecond = (short)newTime.Now.Second;
    28    st.wYear = (short)(newTime.Now.Year);  
    29    return SetSystemTime(ref st);
    30 }
    View Code

    在调用C++编写的Dll动态链接库时常需要注意各种参数的传递问题,以下是摘自http://hi.baidu.com/yun0216/item/f7c856d227465738e3108fa3

    1. 不返回值的参数

    C++ 原型:

    bool    SendNewSms(char *szTel, char *szMessage);

    C#引用;

    [DllImport( "CdmaCard.dll",EntryPoint="SendNewSms")]
    public     static     extern    bool SendNewSms(string phone,string msg);

    2. 带返回值(char *)

    C++原型:

    BOOL GetCardErrorMessage(char *szErrorMessage , int errorCode);

    C#引用

    [DllImport( "CdmaCard.dll",EntryPoint="GetCardErrorMessage")]
         public     static     extern    int GetCardErrorMessage(StringBuilder msg,int errorCode);



    StringBuilder buf = new StringBuilder(1024);//指定的Buf大小必须大于可能的最大长度
           GetCardErrorMessage(buf,1);

    3. 带返回值(其他类型)

    C++原型:

       BOOL GetSmsSaveStation (int *nSmsStation);

    C#引用

       [DllImport( "CdmaCard.dll",EntryPoint="GetSmsSaveStation")]
        public    static    extern   bool GetSmsSaveStation(ref int nStation);

    4. 传递结构体指针(C++填充)
    C++原型:
    struct NET_INFO_STRUCT
    {
       DWORD nDurationTime; //持续时间 
       double nReceiveByte; //接收字节
       double nSendByte;   //发送字节
    };  
    BOOL NetGetConnectDetail(NET_INFO_STRUCT *lpNetInfo);
    C#引用
      
    public struct NET_INFO_STRUCT
    {
       public uint nDurationTime; //持续时间 
       public double nReceiveByte; //接收字节
       public double nSendByte;   //发送字节
    }
    [DllImport( "CdmaCard.dll",EntryPoint="NetGetConnectDetail")]
             public    static    extern   int NetGetConnectDetail(ref NET_INFO_STRUCT pNetInfo);
            
             NET_INFO_STRUCT netInfo = new NET_INFO_STRUCT();
             NetGetConnectDetail(ref netInfo); 
            
    5. 传递结构体数组(C++来填充)
    C++原型:
    struct UIM_BOOK_STRUCT
    {
       int UimIndex;
       char szName[15];
       char szPhone[21];
    };
    int ReadUimAllBook(UIM_BOOK_STRUCT lpUimBookItem[],int nMaxArraySize);

    C#引用
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]//可以指定编码类型
    public struct UIM_BOOK_STRUCT
    {
       public int UimIndex;
       [MarshalAs(UnmanagedType.ByValTStr, SizeConst= 15)]
       public string szName;
       [MarshalAs(UnmanagedType.ByValTStr, SizeConst= 21)]
       public string szPhone;
    };

    [DllImport( "CdmaCard.dll",EntryPoint="ReadUimAllBook")]
    public    static    extern   int ReadUimAllBook([Out] UIM_BOOK_STRUCT [] lpUimBookItem,int nMaxArraySize);

    UIM_BOOK_STRUCT[] p = new UIM_BOOK_STRUCT[20];
    int ret = ReadUimAllBook(p,p.Length);

    6. 注意问题
    类型不一致,会导致调用失败,
    (1) long 类型,在C++中是4字节的整数,在C#中是8字节的整数;
    (2) 字符串类型的设置不正确;

  • 相关阅读:
    CocosCreator 快速开发推箱子游戏,附代码
    Cocos Creator实现左右跳游戏,提供完整游戏代码工程
    Cocos Creator一步一步实现重力球游戏,附完整代码
    PS_制作粉笔字
    高效实用的抠图方法
    PS文件和AI文件之间如何保持分层相互导入?
    行内元素之间出现间隙的bug解决
    CSS中让图片垂直居中的方法
    html中input按钮怎么添加超链接
    【转】Profiler使用方法
  • 原文地址:https://www.cnblogs.com/ouweiqideblog/p/3261709.html
Copyright © 2020-2023  润新知