zoukankan      html  css  js  c++  java
  • 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) 字符串类型的设置不正确;

  • 相关阅读:
    数据流图和数据流程图的定义与组成元素
    敏捷开发3种角色
    WBS
    开发流程
    结对编程
    笔记
    登录注册界面维护2----注册界面进行Toast提示
    登录注册界面修改错误
    听说
    “学习链接篇”
  • 原文地址:https://www.cnblogs.com/ouweiqideblog/p/3261709.html
Copyright © 2011-2022 走看看