您的位置:首页 > 编程语言 > C语言/C++

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;

      }

#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可调用包装器

    这个书不怎么讲这部分。

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

大体看完了,有空仔细研读扩展。做做小东西。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: