• C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅳ部分


    =================================版权声明=================================

    版权声明:本文为博主原创文章 未经许可不得转载 

    请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

    未经作者授权勿用于学术性引用。

    未经作者授权勿用于商业出版、商业印刷、商业引用以及其他商业用途。                   

    本文不定期修正完善,为保证内容正确,建议移步原文处阅读。                                                               <--------总有一天我要自己做一个模板干掉这只土豆

    本文链接:

    耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html

    =======================================================================

     第二十二章 使用非托管代码

      System::Runtime::InteropServices

      GCHandle

        GCHandle::Alloc

        GCHandle::Free

      gcroot辅助模板类

        代替对GCHandle的直接操作

        离开作用域时销毁

      auto_gcroot

        <auto_gcroot.h>

        离开作用域时调用析构函数

      混合类

        托管类中添加指向非托管对象的指针成员

          需要为托管类声明析构函数

          ref Classs ManagedClass

          {

          public:

            ~ManagedClass(){delete m_pUnc;}

          private:

            UnManagedClass* m_pUnC;

          }

        非托管类中添加托管类

          Class UnManagedClass

          {

          public:

            UnManagedClass(gcroot<ManagedClass^> gcrMC):m_gcrMC(gcrMC){}

          private:

            gcroot<ManagedClass^> m_gcrMC;

          }

     1 #include "stdafx.h"
     2 #include <gcroot.h>
     3 #include <iostream>
     4 #include <atlstr.h>
     5 
     6 using namespace System;
     7 using namespace System::Runtime::InteropServices;
     8 ref class CPerson
     9 {
    10 public:
    11     CPerson(int nAge, String^ strName) :m_nAge(nAge),m_strName(strName) {}
    12 
    13     int GetAge() { return m_nAge; }
    14     String^ GetName() { return m_strName; }
    15 
    16 private:
    17     int m_nAge;
    18     String ^ m_strName;
    19 };
    20 
    21 class CPersonInfo
    22 {
    23 public:
    24     CPersonInfo(gcroot<CPerson^> gcroPerson):m_oPerson(gcroPerson){}
    25     int GetAge() { return m_oPerson->GetAge(); }
    26     CString GetName() 
    27     {
    28         return m_oPerson->GetName(); 
    29     }
    30 
    31 private:
    32     gcroot<CPerson^> m_oPerson;
    33 };
    34 
    35 int main(array<System::String ^> ^args)
    36 {
    37     CPerson^ oPerson = gcnew CPerson(11, L"Jack");
    38     CPersonInfo oPersonInfo(oPerson);
    39 
    40     std::wcout << oPersonInfo.GetName().GetString() << L"    " << oPersonInfo.GetAge() <<std::endl;
    41 
    42     return 0;
    43 }

       固定指针

        值不变的托管对象指针

        垃圾回收器不能移动它

        可以安全的传给非托管对象

        固定托管对象的成员造成整个托管对象都被固定

        只要存在对固定指针的引用,托管对象就会一直被固定

     1 #include "stdafx.h"
     2 #include <iostream>
     3 using namespace System;
     4 
     5 void PrintANumber(int * pNumArr)
     6 {
     7     std::cout << *pNumArr << std::endl;
     8 }
     9 
    10 int main(array<System::String ^> ^args)
    11 {
    12     array<int>^ arrNum = gcnew array<int>{11, 22, 33, 44, 55};
    13 
    14     pin_ptr<int> pinNumArr = &arrNum[2];
    15 
    16     PrintANumber(pinNumArr);
    17 
    18     pinNumArr = nullptr;
    19 
    20     return 0;
    21 }

      dynamic_cast不匹配时返回null

      safe_cast不匹配时抛出异常

      包装了简单值的任何东西,只要大小不超过16字节就是和设计成值类型。

      装箱

        C++/CLI自动装箱

        装箱会发生值类型的按位拷贝

      拆箱

        通过强制类型转换

        safe_cast<>()

     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 
     6 int main(array<System::String ^> ^args)
     7 {
     8     int nNum = 12;
     9     Console::WriteLine(nNum);
    10 
    11     Object^ obj12 = nNum;
    12     Console::WriteLine(obj12);
    13 
    14     int nNum12 = safe_cast<int>(obj12);
    15     Console::WriteLine(nNum12);
    16 
    17     return 0;
    18 }

       P/Invoke

        封送  在托管代码和非托管代码之间传递数据/在托管代码和非托管代码之间自动转换 

    #include "stdafx.h"                                                                
                                                                                       
    using namespace System;                                                            
                                                                                       
    using namespace System::Runtime::InteropServices;                                  
                                                                                       
    [DllImport("User32.dll",CharSet=CharSet::Auto)]                                    
                                                                                       
    //int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType )       
    int MessageBox(IntPtr hWnd, String^ lpText, String^ lpCaption, unsigned int uType);
                                                                                       
    int main(array<System::String ^> ^args)                                            
    {                                                                                  
       // Console::WriteLine(L"Hello World");                                          
    	String^ strText = L"Text";                                                        
    	String^ strCaption = L"Caption";                                                  
    	MessageBox(IntPtr::Zero, strText, strCaption,0);                                  
                                                                                       
        return 0;                                                                      
    }                                                                                  
    
    #include "stdafx.h"
    
    using namespace System;
    
    using namespace System::Runtime::InteropServices;
    
    [DllImport("User32.dll", EntryPoint="MessageBox",CharSet = CharSet::Auto)]
    
    //int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType )
    int ShowSomething(IntPtr hWnd, String^ lpText, String^ lpCaption, unsigned int uType);
    
    int main(array<System::String ^> ^args)
    {
    	// Console::WriteLine(L"Hello World");
    	String^ strText = L"Text";
    	String^ strCaption = L"Caption";
    	ShowSomething(IntPtr::Zero, strText, strCaption, 0);
    
    	return 0;
    }
    

      传递结构

        布局

          自动布局LayoutKind::Auto  让运行时优化布局 P/Invoke时不要用

          显式布局LayoutKind::Explicit  按定制的字节偏移量排列

          顺序布局LayoutKind::Sequential  托管和非托管同样的排列

    #include "stdafx.h"
    
    using namespace System;
    
    using namespace System::Runtime::InteropServices;
    
    [StructLayoutAttribute(LayoutKind::Sequential)]
    ref class CPowerState
    {
    public:
    	System::Byte ACLineStatus;
    	System::Byte BatteryFlag;
    	System::Byte BatteryLifePercent;
    	System::Byte ReservedforNow;
    	System::UInt32 BatteryLifeTime;
    	System::UInt32 BatteryFullLifeTime;
    };
    
    typedef long BOOL;
    
    [DllImportAttribute("Kernel32.dll")]
    BOOL GetSystemPowerStatus(CPowerState^ PS);
    
    int main(array<System::String ^> ^args)
    {
       // Console::WriteLine(L"Hello World");
    	CPowerState^ oPS=gcnew CPowerState();
    	BOOL bRet=GetSystemPowerStatus(oPS);
    
        return 0;
    }
    

    =======================================================================

     第二十三章 特性和反射

       元数据

        不知道在说什么

      使用预定义特性类

     1 #pragma once
     2 
     3 using namespace System;
     4 
     5 namespace MyDll {
     6 
     7     public ref class CTestClass
     8     {
     9         // TODO:  在此处添加此类的方法。
    10     public:
    11         CTestClass(int nVal):m_nVal(nVal){}
    12 
    13         [ObsoleteAttribute("Use the Var Property instead",false)]
    14         int GetVal() { return m_nVal; }
    15         
    16         property int Val
    17         {
    18             int get() { return m_nVal; }
    19         }
    20 
    21     private:
    22         int m_nVal;
    23 
    24     };
    25 }
     1 using namespace System;
     2 
     3 using namespace MyDll;
     4 
     5 int main(array<System::String ^> ^args)
     6 {
     7     CTestClass^ oTC = gcnew CTestClass(666);
     8     int nVal = oTC->GetVal();
     9     Console::WriteLine(L"{0}",nVal);
    10 
    11     return 0;
    12 }

       定义自己的特性

        特性类

          定位参数  必选参数  只读属性

          具名参数  可选参数  读写属性

        

     1 // CustomAttributes.h
     2 
     3 #pragma once
     4 
     5 using namespace System;
     6 
     7 namespace CustomAttributes {
     8 
     9     [AttributeUsageAttribute(AttributeTargets::Method|AttributeTargets::Property| AttributeTargets::Class)]
    10     public ref class DocumentationAttributes:Attribute 
    11     {
    12         // TODO:  在此处添加此类的方法。
    13     public:
    14         DocumentationAttributes(String^ strText):m_strText(strText) {};
    15         
    16         property String^ Text
    17         {
    18             String^ get(){return m_strText;}
    19         }
    20 
    21         property String^ Author
    22         {
    23             String^ get() { return m_strAuthor; }
    24             void set(String^ strAuthor) { m_strAuthor=strAuthor; }
    25         }
    26         property String^ Date
    27         {
    28             String^ get() { return m_strDate; }
    29             void set(String^ strDate) { m_strDate = strDate; }
    30         }
    31 
    32     private:
    33         String^ m_strText;
    34         String^ m_strAuthor;
    35         String^ m_strDate;
    36     };
    37 }
     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 using namespace CustomAttributes;
     6 
     7 [DocumentationAttributes("The TestAttrs class",Author="WLS")]
     8 ref class TestAttrs
     9 {
    10 public:
    11     [DocumentationAttributes("The TestAttrs class constructor takes an integer",Author="WLS",Date="2010/01/02")]
    12     TestAttrs(int nV)
    13     {
    14         m_nVal = nV;
    15     }
    16 
    17     [DocumentationAttributes("The read-only Value property returns the value of the int class number", Author = "WLS")]
    18     property int Value
    19     {
    20         int get() { return m_nVal; }
    21     }
    22 
    23 protected:
    24 private:
    25     int m_nVal;
    26 };
    27 
    28 int main(array<System::String ^> ^args)
    29 {
    30     Console::WriteLine(L"Hello World");
    31     return 0;
    32 }

       反射

        不知为何感觉少了点什么编译不通过

        而且对于C++/CLI来说,这个东西主要是用来支持别的语言吧?

     1 // UseAttributes.cpp: 主项目文件。
     2 
     3 #include "stdafx.h"
     4 
     5 
     6 using namespace System;
     7 
     8 using namespace MyDll;
     9 
    10 using namespace::Reflection;
    11 
    12 int main(array<System::String ^> ^args)
    13 {
    14     CTestClass^ oTC = gcnew CTestClass(666);
    15     int nVal = oTC->GetVal();
    16 
    17     Type^ t = oTC->GetType();
    18     array<Object^>^ atts=t->GetCustomAttributes(true);
    19     
    20     array<MemberInfo^>^ mi = t->GetMembers();
    21 
    22     for each(MemberInfo^ m in mi)
    23     {
    24         array<Object^>^ a = m->GetCustomAttributes(true);
    25 
    26         if (a->Length>0)
    27         {
    28             Console::WriteLine("Attributes for member {0}", m->Name);
    29             for each (Object^ attr in a)
    30             {
    31                 Console::WriteLine("attribute is {0}", attr->ToString());
    32 
    33                 //DocumentationAttribute^ Da = dynamic_cast<DocumentationAttribute^>(attr);
    34 
    35             }
    36         }
    37     }
    38 
    39     Console::WriteLine(L"{0}",nVal);
    40 
    41     return 0;
    42 }

     =======================================================================

     第二十四章 兼容COM

      在.NET中使用COM

        RCW  运行时可调用包装器  封送  使用时无差别感受

     1 // ComWrapper.cpp: 主项目文件。
     2 
     3 #include "stdafx.h"
     4 
     5 using namespace System;
     6 
     7 using namespace TempConverterLib;
     8 
     9 int main(array<System::String ^> ^args)
    10 {
    11     Console::WriteLine(L"Hello World");
    12 
    13     TempConverterLib::ConverterClass^ conv= gcnew TempConverterLib::ConverterClass();
    14     
    15     double dF = conv->ConvertC2F(27.0);
    16     
    17     Console::WriteLine("27C is {0} F", dF);
    18 
    19     try
    20     {
    21         double dF = conv->ConvertC2F(-280.0); 
    22           
    23         Console::WriteLine("-280C is {0} F", dF);
    24     }
    25     catch (Exception^ e)
    26     {
    27         Console::WriteLine("Exception  from COM object:{0}", e->Message);
    28     }
    29 
    30     return 0;
    31 }

      晚期绑定

     1 // LateBind.cpp: 主项目文件。
     2 
     3 #include "stdafx.h"
     4 
     5 using namespace System;
     6 
     7 int main(array<System::String ^> ^args)
     8 {
     9     Guid g = Guid("75F3EDC5-AA71-437A-ACB6-F885C29E50F7");
    10 
    11     Type^ t = Type::GetTypeFromCLSID(g);
    12 
    13     if (t==nullptr)
    14     {
    15         Console::WriteLine("1");
    16     }
    17 
    18     Object^ obj = System::Activator::CreateInstance(t);
    19 
    20     array<Object^>^ argarray = { 27.0 };
    21 
    22     try
    23     {
    24         Object^ result = t->InvokeMember("ConvertC2F", Reflection::BindingFlags::InvokeMethod, nullptr, obj, argarray);
    25 
    26         double dF = Convert::ToDouble(result);
    27 
    28         Console::WriteLine("27C is {0}F", dF);
    29     }
    30     catch (Exception^ e)
    31     {
    32         Console::WriteLine("2");
    33     }
    34 
    35     return 0;
    36 }

       把.NET作为COM组件使用

        CCW  COM可调用包装器

        这个书不怎么讲这部分。

    =======================================================================

    大体看完了,有空仔细研读扩展。做做小东西。

  • 相关阅读:
    《财富自由之路》读后感及读书笔记
    echarts3.x 入门
    Ubuntu 16.04 硬盘安装
    语义化版本控制的规范(转载)
    appcan IDE 无法 请求数据
    jQuery extend 函数
    63342 接口 奇遇 IDEA
    C++调用Java的Jar包
    无法打开 源 文件“stdafx.h”的解决方法
    CString的头文件
  • 原文地址:https://www.cnblogs.com/wlsandwho/p/4764678.html
Copyright © 2020-2023  润新知