Variant类型在各语言中的参数传递

简介:

几年前我用VB开发了一个西门子PPI通信控件,由于VB开发的控件是标准的COM组件,所以想当然的认为VC、C#、Delphi等开发语言可以非常容易的使用。

前段时间由于该控件基于微软的MSCOMM控件,这个控件如果系统没有安装VB,单独注册好像很难成功,这害的一些没有装VB的用户,为了这个小控件必须安装一次VB,这实在是划算不来,所以直接用API串口函数进行了封装改进,这样不仅效率提高了,并且再也不需要MSCOMM控件了。

这一次,我不仅使该控件支持了浮点运算,并且在VC、C#(VB当然就不用多试了,以前就很好的支持)进行了兼容测试。

一试问题就来了,没有改进之前的控件,由于C#封装性能甚好,还能使用,唯一不足的是,控件方法中如果不要求返回的参数前面没有添加ByVal参数,在C#中就转换为 ref ***,害的你还得专门定义临时变量进行传参。

在VC中直接就不行,ReadData和WriteData等几个主要方法根本在VC中无法转换成对应函数,具体错误信息如下:

 
  1. // method 'ReadData' not emitted because of invalid return type or parameter type  
  2.  
  3. // method 'WriteData' not emitted because of invalid return type or parameter type  
  4.  
  5. // method 'PlcLogin' not emitted because of invalid return type or parameter type  
  6.  
  7. // method 'PlcRun' not emitted because of invalid return type or parameter type  
  8.  
  9. // method 'PlcStop' not emitted because of invalid return type or parameter type  
  10.  

经过测试,最后发现VB函数中的byte和数组在VC中根本找不到合适的对应。

由于控件中又新添加了浮点数的支持,所以对参数接口又增加了一层复杂性。突然想到微软的MSCOMM控件各语言肯定都能很好的支持,它的接口参数是怎样的定义的。我在VB、VC、C#分别试了一下,VB中和input和Output属性的类型就是Variant类型,在VC中是VARIANT,在C#中是Object。用Variant还有个好处,就是各种类型的数据都可以传输,没有必要在另外添加接口函数了。

最后我定义的接口如下(主要接口):

 
  1. Public Function ReadData(ByVal lngAddr As Long, vData As Variant, Optional ByVal lngNum As Long = 1, Optional ByVal bytLen As PPILEN = PPI_B, Optional ByVal bytType As PPITYPE = PPI_V, Optional ByVal Addr As Long = 0) As Long  
  2.  
  3. Public Function WriteData(ByVal lngAddr As Long, ByVal vData As Variant, Optional ByVal lngNum As Long = 1, Optional ByVal bytLen As PPILEN = PPI_B, Optional ByVal bytType As PPITYPE = PPI_V, Optional ByVal Addr As Long = 0) As Long  
  4.  
  5.    
  6.  

在VC中对应的接口如下:

 

 
  1. long ReadData(long lngAddr, VARIANT* vData, long lngNum, long bytLen, long bytType, long Addr);  
  2.  
  3. long WriteData(long lngAddr, const VARIANT& vData, long lngNum, long bytLen, long bytType, long Addr);  

 

在C#中的接口如下:

    

 
  1. public virtual int ReadData(int lngAddr, ref object vData);  
  2.  
  3.     public virtual int ReadData(int lngAddr, ref object vData, int lngNum, PPILEN bytLen, PPITYPE bytType, int addr);  
  4.  
  5.       public virtual int WriteData(int lngAddr, object vData);  
  6.  
  7.   public virtual int WriteData(int lngAddr, object vData, int lngNum, PPILEN bytLen, PPITYPE bytType, int addr);  

  以为这样定义就万事大吉了,事后一试我又错了,在C#中没有任何问题(看了微软还是在C#上下了很大的功夫),在VC简单的定义一个VARIANT变量直接传递给控件,VB控件老是报错,根本无法使用。后来想为什么MSCOMM控件可以,我的控件不可以。天杀的MSCOMM肯定是VC开发的,而我的控件是VB开发的,VB和C#的包容性都很强,而VC却高高在上不肯屈就。

正一筹莫展准备放弃的时候,突然想到了以前用VC开发的OPC程序,上面有很多关于VARIANT的应用,一看就明白了,原来在VC中VARIANT的用法是有讲究的。

下面我就详细说一下控件同样的接口在不同语言中如何使用。

在VB中:

 

 


Private Sub cmdReadData_Click()

    On Error GoTo ToExit '打开错误陷阱

    '------------------------------------------------

  

 
  1.   Dim i As Long  
  2.  
  3.     Dim bytType As Byte  
  4.  
  5.     Dim lngRet As Long  
  6.  
  7.     Dim lngData() As Long  
  8.  
  9.     Dim fData() As Single  
  10.  
  11.     Dim vData As Variant  
  12.  
  13.    
  14.  
  15.     Select Case cmbType.ListIndex  
  16.  
  17.     Case 0: bytType = PPI_I  
  18.  
  19.     Case 1: bytType = PPI_Q  
  20.  
  21.     Case 2: bytType = PPI_M  
  22.  
  23.     Case 3: bytType = PPI_V  
  24.  
  25.     Case 4: bytType = PPI_S  
  26.  
  27.     Case 5: bytType = PPI_SM  
  28.  
  29.     End Select 
  30.  
  31.    
  32.  
  33.     S7_PPI1.FixAddr = cmbNo.ListIndex + 1  
  34.  
  35.     lngRet = S7_PPI1.ReadData(Val(txtAddr), vData, Val(cmbNum.Text), Val(cmbLen.ListIndex), Val(bytType))  
  36.  
  37.      
  38.  
  39.     If lngRet = 0 Then 
  40.  
  41.         txtData = "" 
  42.  
  43.         If cmbLen.ListIndex = 3 Then 
  44.  
  45.             fData = vData  
  46.  
  47.             For i = 1 To Val(cmbNum.Text)  
  48.  
  49.                 txtData = txtData & Format(fData(i - 1), "0.00") & " " 
  50.  
  51.             Next 
  52.  
  53.         Else 
  54.  
  55.             lngData = vData  
  56.  
  57.             For i = 1 To Val(cmbNum.Text)  
  58.  
  59.                 txtData = txtData & Format(lngData(i - 1), "0") & " " 
  60.  
  61.             Next 
  62.  
  63.         End If  
  64.  
  65.     Else 
  66.  
  67.         txtData = "Error" 
  68.  
  69.     End If  
  70.  
  71.    
  72.  
  73.     '------------------------------------------------  
  74.  
  75.     Exit Sub  
  76.  
  77.     '----------------  
  78.  
  79. ToExit:  
  80.  
  81.     MsgBox Err.Description  
  82.  
  83. End Sub  
  84.  
  85. Private Sub cmdWriteData_Click()  
  86.  
  87.     On Error GoTo ToExit '打开错误陷阱  
  88.  
  89.     '------------------------------------------------  
  90.  
  91.     Dim bytType As Byte  
  92.  
  93.     Dim strData() As String  
  94.  
  95.     Dim lngRet As Long  
  96.  
  97.     Dim lngData(100) As Long  
  98.  
  99.     Dim fData(100) As Single  
  100.  
  101.     Dim i As Long  
  102.  
  103.    
  104.  
  105.     Select Case cmbType.ListIndex  
  106.  
  107.     Case 0: bytType = PPI_I  
  108.  
  109.     Case 1: bytType = PPI_Q  
  110.  
  111.     Case 2: bytType = PPI_M  
  112.  
  113.     Case 3: bytType = PPI_V  
  114.  
  115.     Case 4: bytType = PPI_S  
  116.  
  117.     Case 5: bytType = PPI_SM  
  118.  
  119.     End Select 
  120.  
  121.    
  122.  
  123.     If Len(txtData) > 0 Then 
  124.  
  125.         strData = Split(txtData, " ")  
  126.  
  127.         If cmbLen.ListIndex = 3 Then 
  128.  
  129.             For i = 0 To UBound(strData)  
  130.  
  131.                 fData(i) = Val(strData(i))  
  132.  
  133.             Next 
  134.  
  135.             lngRet = S7_PPI1.WriteData(Val(txtAddr), fData, UBound(strData) + 1, Val(cmbLen.ListIndex), Val(bytType), cmbNo.ListIndex + 1)  
  136.  
  137.         Else 
  138.  
  139.             For i = 0 To UBound(strData)  
  140.  
  141.                 lngData(i) = Val(strData(i))  
  142.  
  143.             Next 
  144.  
  145.             lngRet = S7_PPI1.WriteData(Val(txtAddr), lngData, UBound(strData) + 1, Val(cmbLen.ListIndex), Val(bytType), cmbNo.ListIndex + 1)  
  146.  
  147.         End If  
  148.  
  149.    
  150.  
  151.         If lngRet = 0 Then 
  152.  
  153.             '  
  154.  
  155.         Else 
  156.  
  157.             txtData = "Error" 
  158.  
  159.         End If  
  160.  
  161.     End If  
  162.  
  163.     '------------------------------------------------  
  164.  
  165.     Exit Sub  
  166.  
  167.     '----------------  
  168.  
  169. ToExit:  
  170.  
  171.     MsgBox Err.Description  
  172.  
  173. End Sub  
  174.  
  175.    
  176.  

在C#中:

 


 

 
  1. /// <summary>  
  2.  
  3.         /// 读数据  
  4.  
  5.         /// </summary>  
  6.  
  7.         /// <param name="sender"></param>  
  8.  
  9.         /// <param name="e"></param>  
  10.  
  11.         private void btnRead_Click(object sender, EventArgs e)  
  12.  
  13.         {  
  14.  
  15.             int intAddr = int.Parse(txtFixAddr.Text);  
  16.  
  17.             object vData = new object();  
  18.  
  19.             
  20.  
  21.             /*  
  22.  
  23.             [PPI_I] = &H81  
  24.  
  25.             [PPI_Q] = &H82  
  26.  
  27.             [PPI_M] = &H83  
  28.  
  29.             [PPI_V] = &H84  
  30.  
  31.             [PPI_S] = 4  
  32.  
  33.             [PPI_SM] = 5  
  34.  
  35.             */ 
  36.  
  37.             PPIV2.PPITYPE DataType= PPIV2.PPITYPE.PPI_V;  
  38.  
  39.             switch (cmbDataType.SelectedIndex)  //数据类型  
  40.  
  41.             {  
  42.  
  43.                 case 0:  
  44.  
  45.                     DataType = PPIV2.PPITYPE.PPI_I;  
  46.  
  47.                     break;  
  48.  
  49.                 case 1:  
  50.  
  51.                     DataType = PPIV2.PPITYPE.PPI_Q;  
  52.  
  53.                     break;  
  54.  
  55.                 case 2:  
  56.  
  57.                     DataType = PPIV2.PPITYPE.PPI_M;  
  58.  
  59.                     break;  
  60.  
  61.                 case 3:  
  62.  
  63.                     DataType = PPIV2.PPITYPE.PPI_V;  
  64.  
  65.                     break;  
  66.  
  67.                 case 4:  
  68.  
  69.                     DataType = PPIV2.PPITYPE.PPI_S;  
  70.  
  71.                     break;  
  72.  
  73.                 case 5:  
  74.  
  75.                     DataType = PPIV2.PPITYPE.PPI_SM;  
  76.  
  77.                     break;  
  78.  
  79.             }  
  80.  
  81.             if (axS7_PPI1.ReadData(int.Parse(txtDataAddr.Text), ref vData, cmbLen.SelectedIndex+1  , (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr) == 0)  
  82.  
  83.             {  
  84.  
  85.                 if (cmbDataMode.SelectedIndex == 3)  
  86.  
  87.                 {  
  88.  
  89.                     float[] fData = (float[])vData;  
  90.  
  91.                     txtData.Text = "";  
  92.  
  93.                     for (int i = 0; i < fData.Length; i++)  
  94.  
  95.                     {  
  96.  
  97.                         txtData.Text += fData[i].ToString("0.00") + " ";  
  98.  
  99.                     }  
  100.  
  101.                 }  
  102.  
  103.                 else 
  104.  
  105.                 {  
  106.  
  107.                     Int32[] intData = (Int32[])vData;  
  108.  
  109.                     txtData.Text = "";  
  110.  
  111.                     for (int i = 0; i < intData.Length; i++)  
  112.  
  113.                     {  
  114.  
  115.                         txtData.Text += intData[i].ToString() + " ";  
  116.  
  117.                     }  
  118.  
  119.                 }  
  120.  
  121.             }  
  122.  
  123.             else 
  124.  
  125.             {  
  126.  
  127.                 txtData.Text = "ERROR";  
  128.  
  129.             }  
  130.  
  131.         }  
  132.  
  133.    
  134.  
  135.         /// <summary>  
  136.  
  137.         /// 写数据  
  138.  
  139.         /// </summary>  
  140.  
  141.         /// <param name="sender"></param>  
  142.  
  143.         /// <param name="e"></param>  
  144.  
  145.         private void btnWrite_Click(object sender, EventArgs e)  
  146.  
  147.         {          
  148.  
  149.    
  150.  
  151.             int intAddr = int.Parse(txtFixAddr.Text);  
  152.  
  153.             object vData = new object();  
  154.  
  155.    
  156.  
  157.             /*  
  158.  
  159.             [PPI_I] = &H81  
  160.  
  161.             [PPI_Q] = &H82  
  162.  
  163.             [PPI_M] = &H83  
  164.  
  165.             [PPI_V] = &H84  
  166.  
  167.             [PPI_S] = 4  
  168.  
  169.             [PPI_SM] = 5  
  170.  
  171.             */ 
  172.  
  173.             PPIV2.PPITYPE DataType = PPIV2.PPITYPE.PPI_V;  
  174.  
  175.             switch (cmbDataType.SelectedIndex)  //数据类型  
  176.  
  177.             {  
  178.  
  179.                 case 0:  
  180.  
  181.                     DataType = PPIV2.PPITYPE.PPI_I;  
  182.  
  183.                     break;  
  184.  
  185.                 case 1:  
  186.  
  187.                     DataType = PPIV2.PPITYPE.PPI_Q;  
  188.  
  189.                     break;  
  190.  
  191.                 case 2:  
  192.  
  193.                     DataType = PPIV2.PPITYPE.PPI_M;  
  194.  
  195.                     break;  
  196.  
  197.                 case 3:  
  198.  
  199.                     DataType = PPIV2.PPITYPE.PPI_V;  
  200.  
  201.                     break;  
  202.  
  203.                 case 4:  
  204.  
  205.                     DataType = PPIV2.PPITYPE.PPI_S;  
  206.  
  207.                     break;  
  208.  
  209.                 case 5:  
  210.  
  211.                     DataType = PPIV2.PPITYPE.PPI_SM;  
  212.  
  213.                     break;  
  214.  
  215.             }  
  216.  
  217.             long lngRet = 0;  
  218.  
  219.             if (cmbDataMode.SelectedIndex == 3)  
  220.  
  221.             {  
  222.  
  223.                 float[] fData = new float[100];  
  224.  
  225.                 fData[0] = float.Parse(txtData.Text);  
  226.  
  227.                 lngRet = axS7_PPI1.WriteData(int.Parse(txtDataAddr.Text), fData, 1, (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr);  
  228.  
  229.             }  
  230.  
  231.             else 
  232.  
  233.             {  
  234.  
  235.                 Int32[] intData = new Int32[100];  
  236.  
  237.                 intData[0] = Int32.Parse(txtData.Text);  
  238.  
  239.                 lngRet = axS7_PPI1.WriteData(int.Parse(txtDataAddr.Text), intData, 1, (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr);  
  240.  
  241.             }  
  242.  
  243.             if (lngRet != 0)  
  244.  
  245.             {  
  246.  
  247.                 txtData.Text = "ERROR";  
  248.  
  249.             }  
  250.  
  251.         }  
  252.  
  253.    
  254.  

在VC中:

 


 

 
  1. //读数据  
  2.  
  3. void CPPI_TestDlg::OnReadData()  
  4.  
  5. {  
  6.  
  7.        //pCombo->GetLBText (pCombo->GetCurSel (), strType);  
  8.  
  9.        long lngFixAddr=0,lngDataAddr=0;  
  10.  
  11.        char strAddr[255];  
  12.  
  13.        m_FixAddr.GetWindowText(strAddr,255);  
  14.  
  15.        sscanf(strAddr,"%ld",&lngFixAddr);  
  16.  
  17.         
  18.  
  19.        m_DataAddr.GetWindowText(strAddr,255);  
  20.  
  21.        sscanf(strAddr,"%ld",&lngDataAddr);  
  22.  
  23.     /*  
  24.  
  25.        [PPI_I] = &H81  
  26.  
  27.     [PPI_Q] = &H82  
  28.  
  29.     [PPI_M] = &H83  
  30.  
  31.     [PPI_V] = &H84  
  32.  
  33.     [PPI_S] = 4  
  34.  
  35.     [PPI_SM] = 5  
  36.  
  37.        */ 
  38.  
  39.     long DataType;  
  40.  
  41.        switch (m_DataType.GetCurSel())  //数据类型  
  42.  
  43.        {  
  44.  
  45.        case 0:  
  46.  
  47.               DataType=0x81;   
  48.  
  49.               break;  
  50.  
  51.        case 1:  
  52.  
  53.               DataType=0x82;  
  54.  
  55.               break;  
  56.  
  57.        case 2:  
  58.  
  59.               DataType=0x83;  
  60.  
  61.               break;  
  62.  
  63.        case 3:  
  64.  
  65.               DataType=0x84;  
  66.  
  67.               break;  
  68.  
  69.        case 4:  
  70.  
  71.               DataType=0x4;  
  72.  
  73.               break;  
  74.  
  75.        case 5:  
  76.  
  77.               DataType=0x5;  
  78.  
  79.               break;  
  80.  
  81.        }  
  82.  
  83.    
  84.  
  85.        long lngRet;  
  86.  
  87.     VARIANT vData;  
  88.  
  89.        VariantInit (&vData);  
  90.  
  91.        if(m_DataMode.GetCurSel()==3)  //浮点数  
  92.  
  93.        {  
  94.  
  95.            vData.vt = VT_R4 | VT_ARRAY;  
  96.  
  97.            vData.parray=SafeArrayCreateVector(VT_R4, 0, 255 );      
  98.  
  99.        }  
  100.  
  101.        else 
  102.  
  103.        {  
  104.  
  105.            vData.vt = VT_I4 | VT_ARRAY;  
  106.  
  107.            vData.parray=SafeArrayCreateVector(VT_I4, 0, 255 );     //SAFEARRAY vd;  
  108.  
  109.        }     
  110.  
  111.        lngRet=m_PPI.ReadData(lngDataAddr,&vData,m_DataNum.GetCurSel()+1,m_DataMode.GetCurSel(),DataType,lngFixAddr);  
  112.  
  113.        if(lngRet==0)  
  114.  
  115.        {  
  116.  
  117.               CString strData;  
  118.  
  119.               if(m_DataMode.GetCurSel()==3)  //浮点数  
  120.  
  121.               {  
  122.  
  123.                      float *fData;  
  124.  
  125.                      SafeArrayAccessData(vData.parray, (void**)&fData );  
  126.  
  127.                      for(int i=0;i<m_DataNum.GetCurSel()+1;i++)  //(int)vData.parray->cbElements  
  128.  
  129.                      {  
  130.  
  131.                         CString cData;  
  132.  
  133.                         cData.Format("%04.2f ",fData[i]);  
  134.  
  135.                         strData+= cData;  
  136.  
  137.                      }  
  138.  
  139.                      SafeArrayUnaccessData(vData.parray);  
  140.  
  141.               }  
  142.  
  143.               else 
  144.  
  145.               {  
  146.  
  147.                      long *lngData;  
  148.  
  149.                      SafeArrayAccessData(vData.parray, (void**)&lngData );  
  150.  
  151.                      for(int i=0;i<m_DataNum.GetCurSel()+1;i++)  //(int)vData.parray->cbElements  
  152.  
  153.                      {  
  154.  
  155.                         CString cData;  
  156.  
  157.                         cData.Format("%ld ",lngData[i]);  
  158.  
  159.                         strData+= cData;  
  160.  
  161.                      }  
  162.  
  163.                      SafeArrayUnaccessData(vData.parray);  
  164.  
  165.               }  
  166.  
  167.    
  168.  
  169.               m_Data.SetWindowText(strData);  
  170.  
  171.        }  
  172.  
  173.        else 
  174.  
  175.        {  
  176.  
  177.         m_Data.SetWindowText(_T("ERROR"));  
  178.  
  179.        }  
  180.  
  181.        SafeArrayUnaccessData(vData.parray);  
  182.  
  183.        SafeArrayDestroy(vData.parray);  
  184.  
  185.     VariantClear(&vData);  
  186.  
  187. }  
  188.  
  189.    
  190.  
  191. //写数据  
  192.  
  193. void CPPI_TestDlg::OnWrite()  
  194.  
  195. {  
  196.  
  197.        long lngFixAddr=0,lngDataAddr=0;  
  198.  
  199.        char strAddr[255];  
  200.  
  201.        m_FixAddr.GetWindowText(strAddr,255);  
  202.  
  203.        sscanf(strAddr,"%ld",&lngFixAddr);  
  204.  
  205.         
  206.  
  207.        m_DataAddr.GetWindowText(strAddr,255);  
  208.  
  209.        sscanf(strAddr,"%ld",&lngDataAddr);  
  210.  
  211.    
  212.  
  213.     long DataType;  
  214.  
  215.        switch (m_DataType.GetCurSel())  
  216.  
  217.        {  
  218.  
  219.        case 0:  
  220.  
  221.               DataType=0x81;  
  222.  
  223.               break;  
  224.  
  225.        case 1:  
  226.  
  227.               DataType=0x82;  
  228.  
  229.               break;  
  230.  
  231.        case 2:  
  232.  
  233.               DataType=0x83;  
  234.  
  235.               break;  
  236.  
  237.        case 3:  
  238.  
  239.               DataType=0x84;  
  240.  
  241.               break;  
  242.  
  243.        case 4:  
  244.  
  245.               DataType=0x4;  
  246.  
  247.               break;  
  248.  
  249.        case 5:  
  250.  
  251.               DataType=0x5;  
  252.  
  253.               break;  
  254.  
  255.        }  
  256.  
  257.        long lngRet;  
  258.  
  259.     VARIANT vData;  
  260.  
  261.        VariantInit (&vData);  
  262.  
  263.        if(m_DataMode.GetCurSel()==3)  //浮点数  
  264.  
  265.        {  
  266.  
  267.            vData.vt = VT_R4 | VT_ARRAY;  
  268.  
  269.            vData.parray=SafeArrayCreateVector(VT_R4, 0, 255 );  
  270.  
  271.                
  272.  
  273.               float *fDatas,fData;  
  274.  
  275.               SafeArrayAccessData(vData.parray, (void**)&fDatas );  
  276.  
  277.               m_Data.GetWindowText(strAddr,255);  
  278.  
  279.               sscanf(strAddr,"%f",&fData);  
  280.  
  281.               fDatas[0]=fData;  
  282.  
  283.               SafeArrayUnaccessData(vData.parray);  
  284.  
  285.        }  
  286.  
  287.        else 
  288.  
  289.        {  
  290.  
  291.            vData.vt = VT_I4 | VT_ARRAY;  
  292.  
  293.            vData.parray=SafeArrayCreateVector(VT_I4, 0, 255 );     //SAFEARRAY vd;  
  294.  
  295.                
  296.  
  297.               long *lngDatas,lngData;  
  298.  
  299.               SafeArrayAccessData(vData.parray, (void**)&lngDatas );  
  300.  
  301.               m_Data.GetWindowText(strAddr,255);  
  302.  
  303.               sscanf(strAddr,"%ld",&lngData);  
  304.  
  305.               lngDatas[0]=lngData;  
  306.  
  307.               SafeArrayUnaccessData(vData.parray);  
  308.  
  309.        }  
  310.  
  311.    
  312.  
  313.     lngRet=m_PPI.WriteData(lngDataAddr,(const VARIANT &)vData,1,m_DataMode.GetCurSel(),DataType,lngFixAddr);  
  314.  
  315.        if(lngRet!=0)  
  316.  
  317.        {  
  318.  
  319.               m_Data.SetWindowText(_T("ERROR"));  
  320.  
  321.        }  
  322.  
  323.        SafeArrayUnaccessData(vData.parray);  
  324.  
  325.        SafeArrayDestroy(vData.parray);  
  326.  
  327.     VariantClear(&vData);  
  328.  
  329. }  
  330.  
  331.    
  332.  

详细的示例请在下面的链接下载:

http://www.sky-walker.com.cn/yefan/PPIV2.rar

 

早期版本的控件下载链接:

http://www.sky-walker.com.cn/yefan/S7_PPI.rar














本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/323423,如需转载请自行联系原作者

相关文章
|
3天前
|
Java C# 开发者
Python 中的类型注解是一种用于描述变量、函数参数和返回值预期类型的机制
【5月更文挑战第8天】Python的类型注解提升代码可读性和可维护性,虽非强制,但利于静态类型检查(如Mypy)。包括:变量注解、函数参数和返回值注解,使用内置或`typing`模块的复杂类型,自定义类型注解,以及泛型模拟。类型注解可在变量声明、函数定义和注释中使用,帮助避免类型错误,提高开发效率。
23 6
|
3天前
|
安全 Swift
Swift 语言:什么是可选类型(Optional)?如何处理可选类型的安全解包?
Swift的可选类型是处理值可能缺失的类,用?表示。它们能表示有值或无值状态。安全解包用`if let`或`guard let`避免崩溃,而强制解包`!`则风险较高,若值为`nil`会触发运行时错误。
9 0
|
3天前
|
存储 C++
在C++语言中函数指针的作用类型
在C++语言中函数指针的作用类型
11 0
|
3天前
|
存储 Rust 安全
Rust中的变量与常量:定义与使用的深入解析
本文将详细探讨Rust编程语言中变量与常量的定义、特性及其使用场景。我们将从基本概念出发,逐步深入到Rust的内存管理、所有权系统和不变性原则,帮助读者更好地理解和应用这两种基础元素。
|
3天前
|
C++ Rust NoSQL
Rust 数据类型 之 类C枚举 c-like enum
Rust 数据类型 之 类C枚举 c-like enum
34 0
Rust 数据类型 之 类C枚举 c-like enum
|
6月前
|
Go
详细介绍 Go 语言中函数的特点、定义、参数传递、返回值、匿名函数
详细介绍 Go 语言中函数的特点、定义、参数传递、返回值、匿名函数
123 39
详细介绍 Go 语言中函数的特点、定义、参数传递、返回值、匿名函数
|
10月前
|
存储 安全 算法
02-📝C++核心语法|C++对C的扩展【::作用域运算符、名字控制、struct类型加强、C/C++中的const、引用(reference)、函数】
复习`C++核心语法`,且适当进行汇编探索底层实现原理,进一步夯实基础,为以后的`底层开发`、`音视频开发`、`跨平台开发`、`算法`等方向的进一步学习埋下伏笔。
02-📝C++核心语法|C++对C的扩展【::作用域运算符、名字控制、struct类型加强、C/C++中的const、引用(reference)、函数】
|
PHP 开发者
强类型返回值|学习笔记
快速学习强类型返回值
85 0
强类型返回值|学习笔记
【Swift4】(5) 函数基本使用 | 可变参数 | inout引用传递 | 函数类型返回值 | 函数嵌套
【Swift4】(5) 函数基本使用 | 可变参数 | inout引用传递 | 函数类型返回值 | 函数嵌套
160 0
|
Kotlin
【Kotlin】函数类型 ( 函数类型 | 带参数名称的参数列表 | 可空函数类型 | 复杂函数类型 | 带接收者函数类型 | 函数类型别名 | 函数类型实例化 | 函数调用 )(二)
【Kotlin】函数类型 ( 函数类型 | 带参数名称的参数列表 | 可空函数类型 | 复杂函数类型 | 带接收者函数类型 | 函数类型别名 | 函数类型实例化 | 函数调用 )(二)
199 0