C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅳ部分
2015-09-05 21:47
519 查看
=================================版权声明=================================
[b]版权声明:本文为博主原创文章 未经许可不得转载
[/b]
请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
未经作者授权勿用于学术性引用。
未经作者授权勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善,为保证内容正确,建议移步原文处阅读。 <--------总有一天我要自己做一个模板干掉这只土豆
本文链接:
耻辱墙:/article/5266550.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;
}
固定指针
值不变的托管对象指针
垃圾回收器不能移动它
可以安全的传给非托管对象
固定托管对象的成员造成整个托管对象都被固定
只要存在对固定指针的引用,托管对象就会一直被固定
dynamic_cast不匹配时返回null
safe_cast不匹配时抛出异常
包装了简单值的任何东西,只要大小不超过16字节就是和设计成值类型。
装箱
C++/CLI自动装箱
装箱会发生值类型的按位拷贝
拆箱
通过强制类型转换
safe_cast<>()
P/Invoke
封送 在托管代码和非托管代码之间传递数据/在托管代码和非托管代码之间自动转换
传递结构
布局
自动布局LayoutKind::Auto 让运行时优化布局 P/Invoke时不要用
显式布局LayoutKind::Explicit 按定制的字节偏移量排列
顺序布局LayoutKind::Sequential 托管和非托管同样的排列
=======================================================================
第二十三章 特性和反射
元数据
不知道在说什么
使用预定义特性类
定义自己的特性
特性类
定位参数 必选参数 只读属性
具名参数 可选参数 读写属性
反射
不知为何感觉少了点什么编译不通过
而且对于C++/CLI来说,这个东西主要是用来支持别的语言吧?
=======================================================================
第二十四章 兼容COM
在.NET中使用COM
RCW 运行时可调用包装器 封送 使用时无差别感受
晚期绑定
把.NET作为COM组件使用
CCW COM可调用包装器
这个书不怎么讲这部分。
=======================================================================
大体看完了,有空仔细研读扩展。做做小东西。
[b]版权声明:本文为博主原创文章 未经许可不得转载
[/b]
请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
未经作者授权勿用于学术性引用。
未经作者授权勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善,为保证内容正确,建议移步原文处阅读。 <--------总有一天我要自己做一个模板干掉这只土豆
本文链接:
耻辱墙:/article/5266550.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;
}
#include "stdafx.h" #include <gcroot.h> #include <iostream> #include <atlstr.h> using namespace System; using namespace System::Runtime::InteropServices; ref class CPerson { public: CPerson(int nAge, String^ strName) :m_nAge(nAge),m_strName(strName) {} int GetAge() { return m_nAge; } String^ GetName() { return m_strName; } private: int m_nAge; String ^ m_strName; }; class CPersonInfo { public: CPersonInfo(gcroot<CPerson^> gcroPerson):m_oPerson(gcroPerson){} int GetAge() { return m_oPerson->GetAge(); } CString GetName() { return m_oPerson->GetName(); } private: gcroot<CPerson^> m_oPerson; }; int main(array<System::String ^> ^args) { CPerson^ oPerson = gcnew CPerson(11, L"Jack"); CPersonInfo oPersonInfo(oPerson); std::wcout << oPersonInfo.GetName().GetString() << L" " << oPersonInfo.GetAge() <<std::endl; return 0; }
固定指针
值不变的托管对象指针
垃圾回收器不能移动它
可以安全的传给非托管对象
固定托管对象的成员造成整个托管对象都被固定
只要存在对固定指针的引用,托管对象就会一直被固定
#include "stdafx.h" #include <iostream> using namespace System; void PrintANumber(int * pNumArr) { std::cout << *pNumArr << std::endl; } int main(array<System::String ^> ^args) { array<int>^ arrNum = gcnew array<int>{11, 22, 33, 44, 55}; pin_ptr<int> pinNumArr = &arrNum[2]; PrintANumber(pinNumArr); pinNumArr = nullptr; return 0; }
dynamic_cast不匹配时返回null
safe_cast不匹配时抛出异常
包装了简单值的任何东西,只要大小不超过16字节就是和设计成值类型。
装箱
C++/CLI自动装箱
装箱会发生值类型的按位拷贝
拆箱
通过强制类型转换
safe_cast<>()
#include "stdafx.h" using namespace System; int main(array<System::String ^> ^args) { int nNum = 12; Console::WriteLine(nNum); Object^ obj12 = nNum; Console::WriteLine(obj12); int nNum12 = safe_cast<int>(obj12); Console::WriteLine(nNum12); return 0; }
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; }
=======================================================================
第二十三章 特性和反射
元数据
不知道在说什么
使用预定义特性类
#pragma once using namespace System; namespace MyDll { public ref class CTestClass { // TODO: 在此处添加此类的方法。 public: CTestClass(int nVal):m_nVal(nVal){} [ObsoleteAttribute("Use the Var Property instead",false)] int GetVal() { return m_nVal; } property int Val { int get() { return m_nVal; } } private: int m_nVal; }; }
using namespace System; using namespace MyDll; int main(array<System::String ^> ^args) { CTestClass^ oTC = gcnew CTestClass(666); int nVal = oTC->GetVal(); Console::WriteLine(L"{0}",nVal); return 0; }
定义自己的特性
特性类
定位参数 必选参数 只读属性
具名参数 可选参数 读写属性
// CustomAttributes.h #pragma once using namespace System; namespace CustomAttributes { [AttributeUsageAttribute(AttributeTargets::Method|AttributeTargets::Property| AttributeTargets::Class)] public ref class DocumentationAttributes:Attribute { // TODO: 在此处添加此类的方法。 public: DocumentationAttributes(String^ strText):m_strText(strText) {}; property String^ Text { String^ get(){return m_strText;} } property String^ Author { String^ get() { return m_strAuthor; } void set(String^ strAuthor) { m_strAuthor=strAuthor; } } property String^ Date { String^ get() { return m_strDate; } void set(String^ strDate) { m_strDate = strDate; } } private: String^ m_strText; String^ m_strAuthor; String^ m_strDate; }; }
#include "stdafx.h" using namespace System; using namespace CustomAttributes; [DocumentationAttributes("The TestAttrs class",Author="WLS")] ref class TestAttrs { public: [DocumentationAttributes("The TestAttrs class constructor takes an integer",Author="WLS",Date="2010/01/02")] TestAttrs(int nV) { m_nVal = nV; } [DocumentationAttributes("The read-only Value property returns the value of the int class number", Author = "WLS")] property int Value { int get() { return m_nVal; } } protected: private: int m_nVal; }; int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); return 0; }
反射
不知为何感觉少了点什么编译不通过
而且对于C++/CLI来说,这个东西主要是用来支持别的语言吧?
// UseAttributes.cpp: 主项目文件。 #include "stdafx.h" using namespace System; using namespace MyDll; using namespace::Reflection; int main(array<System::String ^> ^args) { CTestClass^ oTC = gcnew CTestClass(666); int nVal = oTC->GetVal(); Type^ t = oTC->GetType(); array<Object^>^ atts=t->GetCustomAttributes(true); array<MemberInfo^>^ mi = t->GetMembers(); for each(MemberInfo^ m in mi) { array<Object^>^ a = m->GetCustomAttributes(true); if (a->Length>0) { Console::WriteLine("Attributes for member {0}", m->Name); for each (Object^ attr in a) { Console::WriteLine("attribute is {0}", attr->ToString()); //DocumentationAttribute^ Da = dynamic_cast<DocumentationAttribute^>(attr); } } } Console::WriteLine(L"{0}",nVal); return 0; }
=======================================================================
第二十四章 兼容COM
在.NET中使用COM
RCW 运行时可调用包装器 封送 使用时无差别感受
// ComWrapper.cpp: 主项目文件。 #include "stdafx.h" using namespace System; using namespace TempConverterLib; int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); TempConverterLib::ConverterClass^ conv= gcnew TempConverterLib::ConverterClass(); double dF = conv->ConvertC2F(27.0); Console::WriteLine("27C is {0} F", dF); try { double dF = conv->ConvertC2F(-280.0); Console::WriteLine("-280C is {0} F", dF); } catch (Exception^ e) { Console::WriteLine("Exception from COM object:{0}", e->Message); } return 0; }
晚期绑定
// LateBind.cpp: 主项目文件。 #include "stdafx.h" using namespace System; int main(array<System::String ^> ^args) { Guid g = Guid("75F3EDC5-AA71-437A-ACB6-F885C29E50F7"); Type^ t = Type::GetTypeFromCLSID(g); if (t==nullptr) { Console::WriteLine("1"); } Object^ obj = System::Activator::CreateInstance(t); array<Object^>^ argarray = { 27.0 }; try { Object^ result = t->InvokeMember("ConvertC2F", Reflection::BindingFlags::InvokeMethod, nullptr, obj, argarray); double dF = Convert::ToDouble(result); Console::WriteLine("27C is {0}F", dF); } catch (Exception^ e) { Console::WriteLine("2"); } return 0; }
把.NET作为COM组件使用
CCW COM可调用包装器
这个书不怎么讲这部分。
=======================================================================
大体看完了,有空仔细研读扩展。做做小东西。