Pointers vs Handles vs Native Types
^ similar to *
% similar to &
N* pn = new N; // allocate on native heap
N& rn = *pn; // bind ordinary reference to native object
R% rr = *hr; // bind tracking reference to gc-lvalueR^ hr = gcnew R; // allocate on CLI heap
Boxing, Unboxing:
Boxing implicit.
Unboxing explicit: need a reinterpret_cast and then dereference.
int i = 1024;
int^ boxedi = i; //Implicit boxing, boxedi doesn’t point to i;
// A bit-wise copy is performed // an int Object is created on the CLR heap //Can use safe_cast<int^>(i) to explicitly castObject^ o = i; //Another implicit boxing
int k = *safe_cast<int^>(o); //unboxing
//Type-safe: When you box a value-type, // the returned object remembers the original value type.//reinterpret_cast could be used, safe_cast is better// to create safe code (to compile with /clr:safe) Console::WriteLine(o->GetType()); //same with typeid<o>?// Output:
// System.Int32//Can not cast to a different type!
float g = *reinterpret_cast<float^>(o); //System.InvalidCastException
// Cap or handle (^) denotes managed object reference // (.NET reference types) // (instead of *). // Delete optional, // Garbage Collector will handle. // These don't have a fixed memory address // they will be moved around during execution // Type-safe (you cannot cast a handle to a void^)
Class (and struct) declarations :
class native {}; //Following create CLI types
value class V {}; // “value” => stack types beyond primitive types // all value types derive from System::ValueType
ref class R {}; // “ref” => managed class, instantiated with R^
interface class I {};
native enum & cli class enum:
enum native_Enum { fail, pass };enum class cli_Enum: char { fail, pass}; public enum class cli_SomeColors { Red, Yellow, Blue};
Arrays
array<int>^ ia = gcnew array<int>{1,1,2,3,5,8}; // gcnew retuns handle (new returns pointer)
// same with cli::array ia = gcnew array<int>(10){2,5}; //creates array of size 10, //all after first two elements initialized to 0
Interior Pointer
to access to memory within objects.
Lets you do pointer arithmetic.
Dangerous feature.
GC keeps track of changes in memory location and updates the interior pointer unless interior pointer is used by unmanaged code!
const int SIZE = 10;
array<int>^ a = gcnew array<int>(SIZE);
interior_ptr<int> p = &a[0];
for (int i = 0; i < SIZE; ++i, ++p)
*p = i;
Pin Pointer
Pins the object in memory (GC doesn’t move it around), so the pointer won’t point to invalid memory.
value struct smallInt { int m_ival; ... } si;
pin_ptr<int> ppi = &si.m_ival; // assign nullptr to pin pointer after its use is over // so that GC knows it can now move the object around
Iterating Managed Arrays
//For each to iterate, but//Length attribute and the index also available for each (int v in a)
{
Console::WriteLine("value={0}", v);
}
3D Array Creation
//All cells are initialized to 0 automaticallyarray<int, 3> ^threed = gcnew array<int, 3>(4,5,2);
Console::WriteLine(threed[0,0,0]);
Another example for handles
//This shows a window using WPFApplication().Run(%Window()); // % for referencing
//===== equivalent toWindow w;
Application().Run(%w);//===== equivalent toWindow ^w = gcnew Window();
Application().Run(w); // no need to reference, pass handle//===== equivalent toWindow ^w = gcnew Window();
Application ^a1 = gcnew Application();
a1->Run(w);//===== equivalent toWindow ^w = gcnew Window();
Application ^a1 = gcnew Application();
a1->Run(w); // similar to pointer handles use ->//===== equivalent toApplication ^a1 = gcnew Application();
Application %a2 = *a1;//like pointers, dereferencing via *
a2.Run(w);
Array of strings and using Tracking reference “^%” to iterate:
similar to “*&” (reference to a pointer) in Standard C++
array<String^>^ arr = gcnew array<String^>(10);
int i = 0;
for each(String^% s in arr) s = i++.ToString(); //redundant: s = gcnew String( (i++).ToString() );
New parameter for main function
#using <mscorlib.dll> //you don’t have to include this anymore //automatically included whenever u compile with /clr
using namespace System;
int main(array<System::String ^> ^args)
{
System::Console::WriteLine("Hello world");
return 0;
}
Finalizer vs Deterministic Destructor
Non-managed resources must be Deterministically destroyed.
Deterministic destruction recommended for system-wide limited resources (network/database connections, file streams, etc.).
Even with deterministic destructor also create a finalizer (GC-destructor) that just checks whether the destructor has been invoked and calls it if it hasn’t.
// C++/CLI
ref class MyClass // : IDisposable (added by the compiler)
{
public:
MyClass(); // constructor
~MyClass(); // (deterministic) destructor // turned into IDisposable.Dispose() by compiler // corresponds to Dispose() in C#
protected:
!MyClass(); // finalizer // corresponds to ~MyClass() in C#
public:
static void Test()
{
MyClass automatic; //compiler calls constructor here automatically //will be destroyed by compiler when out of scope
// Equivalent user code:
MyClass^ user = gcnew MyClass();
try { /* Use user here */ } finally { delete user; }
// Compiler calls automatic's destructor in the // finally of a try containing the whole method
}
};
Restricting what kind of classes can be used for template type(s):
generic<class T> where T : IDisposable
ref class DisposableType
{
T t;
public:
DisposableType(T param) {t=param;}
void Close()
{
t->Dispose(); //since there is constraint on what T can be // no need to cast t to use IDisposable methods
}
};
Constraints also possible for generic methods:
interface class IPrintable
{
void Print();
};
ref class Printer
{
public:
generic<class T> where T : IPrintable
void PrintDoc(T doc)
{
doc->Print(); //no need to cast doc
}
};
Properties
// LibCLI.h
#pragma once
using namespace System;
namespace LibCLI {
public ref class Person
{
private:
String^ _name;
public:
// The constructor. // there is no _age, only property Age! // see last line
Person( String^ name, int age )
{
Name = name;
Age = age;
}
// property for the member _name
property String^ Name
{
String^ get()
{
return _name;
}
void set(String^ name)
{
_name = name;
}
}
// A trivial property. No need to define
// the getter and setter, compiler does it for you.
property int Age;
};
}
Operator overloading
static for handles; casting to Object^ will remove the overloading semantics
{ String ^s1 = "abc";
String ^s2 = "ab" + "c";
Object ^o1 = s1;
Object ^o2 = s2;
s1 == s2; // true
o1 == o2; // false}
Parameter Array
void avg(String ^msg, ... array<int> ^values)
{ // “...” denotes parameter array, // used to be [ParamArray]attribute before
int tot = 0;
for each (int v in values)
tot += v;
Console::WriteLine("{0} {1}", msg, tot / values->Length);
}
int main(array<String ^> ^args)
{
avg("The avg is:", 1,2,3,4,5);
return 0;
}
Wrapping your C++ classes:
provides deterministic finalization of garbage- collected types. Ex: Wrapping class named Native
ref class Wrapper {
Native *pn;
public:
// resource acquisition is initialization
Wrapper( int val ) { pn = new Native( val ); }
// this will do our disposition of the native memory
~Wrapper(){ delete pn; }
void mfunc();
protected:
// an explicit Finalize() method—as a failsafe
!Wrapper() { delete pn; }
};
void f1()
{
// normal treatment of a reference type
Wrapper^ w1 = gcnew Wrapper( 1024 );
// mapping a reference type to a lifetime
Wrapper w2( 2048 ); // no ^ token !
// just illustrating a semantic difference
w1->mfunc();
w2.mfunc();
// w2 is disposed of here automatically
}
//
// ... later, w1 may be finalized at some point
Another more complete wrapper template ref class with operator overloading, copy constructor and assignment operator
template <typename T>
public ref class ptr_wrapper sealed
{
private:
T *m_ptr;
ptr_wrapper(T *i_ptr)
:m_ptr(i_ptr)
{
if (i_ptr == 0)
{
throw gcnew System::Exception( "Trying to initialize ptr_wrapper with null pointer");
}
}
public:
ptr_wrapper(const T &i_ref)
:m_ptr(new T(i_ref))
{
}
ptr_wrapper(const ptr_wrapper %i_other)
:m_ptr(new T(const_cast<const T&>(*i_other)))
{
}
static ptr_wrapper take(T *i_ptr)
{
return ptr_wrapper(i_ptr);
}
~ptr_wrapper()
{
delete m_ptr;
}
ptr_wrapper % operator = (const ptr_wrapper %other)
{
if (other.m_ptr != m_ptr)
{
T* new_ptr = new T(*other);
delete m_ptr;
m_ptr = new_ptr;
}
}
static T& operator * (ptr_wrapper<T> %inst)
{
return *(inst.m_ptr);
}
static const T& operator * (const ptr_wrapper %inst)
{
return *(inst.m_ptr);
}
static T* operator -> (ptr_wrapper %inst)
{
return inst.m_ptr;
}
static const T* operator -> (const ptr_wrapper<T> %inst)
{
return inst.m_ptr;
}
};
Command line building
# run the script to set up environment
# use with quotes!
# path assumes VS 2008 (i.e 9.0) installed
”C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat”
# then compile
cl your_file.cpp /clr
Glossary
Garbage Collector (GC): reclaims garbage, or memory used by objects that will never be accessed or mutated again by the application.
Common Language Infrastructure (CLI): It is an open specification that defines a runtime environment that allows multiple high-level languages to be used on different computer platforms without being rewritten for specific architectures. [Specification]
Common Type System (CTS): a standard that specifies how Type definitions and specific values of Types are represented in computer memory, so programs in different programming languages can easily share information.
Base Class Library (BCL): a standard library available to all languages using the .NET Framework, comparable in scope to the standard libraries of Java.
Framework Class Library (FCL): a collection of thousands of reusable classes, interfaces and value types, within hundreds of namespaces. BCL is a part of FCL and provide the most fundamental functionality. [Namespaces Poster]
[Class Libraries for .Net 3.5]
Windows Presentation Foundation (WPF):graphical subsystem in .NET Framework 3.0, which uses XAML markup language, for rich user interface development. Microsoft Expression Blend is a designer tool that generates XAML that may be exported into other tools.
[MSDN section]
managed classes: objects are under .NET automatic garbage collection (vs objects the programmer must remember to explicitly destroy)
value type (vs reference type): a data type that directly contain their data (rather than through a reference or pointer), allocated on the stack or allocated inline in a structure.
reference type (vs value type): data type that can be instantiated via dynamic memory allocation.
References
Best Quick Articles are from The Code Project: Quick C++/CLI – Learn C++/CLI in less than 10 minutes and A first look at C++/CLI
Article by Stanley B. Lippman from Microsoft: Pure C++ Hello, C++/CLI
Article by Richard Grimes from DDJ: New Syntax C++ in .NET Version 2
Tutorials on functionx.com [C++/CLI, VC/CLI, also VC.NET]
Resources
MSDN website is full of useful materials, but hard to find, here is some gems I found.
If you would like to teach C++:
Free Ebook by Herbert Schildt,
and other higher level C++ educational materials at MSDN Developer Learning Center: beginner, all levels, all levels
Root for all educational materials: Developer Centers
MSDN Library download
(Full Library of 2GB is on second link)
MUI Information:
MS Technology to support easy translation of developed applications