Title: Moving C Applications to the Common Language Runtime
1Moving C Applications to the Common Language
Runtime
- Kate Gregory
- Gregory Consulting Limited
- kate_at_gregcons.com
2Visual C through the years
3Why move code to the CLR?
- CLR provides services to running code
- Memory management
- Security
-
- Managed libraries provide convenience
- Process XML
- Encryption
- Wrapper around OS functionality
- GUI building
- Exposing your code onto the runtime lets others
automate it - Saves writing a scripting engine or COM
interfaces - Simplifies interop with partners
4Why not move code to the CLR?
- Needs the runtime to execute
- Concern about execution speed of managed code
- Managed code is fast, but transition between
worlds costs - Placing your managed/unmanaged boundary is vital
- C is the language of choice for this careful
boundary placement - Concern over longevity of code base
- Microsoft has issued a total commitment to the
future of the code base written to C/CLI - Uncertainty about loss of C features
- C/CLI retains true C flavour and capabilities
5Why not just go to C?
- Why learn another language?
- C has faster interop
- C has better optimization, even when generating
MSIL - C has deterministic destruction, even for
managed types - C can have higher developer productivity
- STL
- Template specialization
6Managed Code Optimizations
- Compiler optimizes MSIL
- Even when generating verifiable code
- Some optimizations supported on MSIL
- Inlining
- Loop unrolling
- Loop invariant code motion
- Common subexpression elimination
- Copy propagation
- Expression optimizations
- Whole program optimization now supported for /clr
code
7C ? CLR
- C Features
- Deterministic cleanup, destructors
- Templates
- Native types
- Multiple inheritance
- STL, generic algorithms
- Pointer/pointee distinction
- Copy construction, assignment
- CLR Features
- Garbage collection, finalizers
- Generics
- Reference and value types
- Interfaces
- Verifiability
- Security
- Properties, delegates, events
8The CLR Supports You
- The CLR makes a number of services available to
applications - Garbage collection and resource management
- Cross-language development
- Security demands for partially trusted code
- Making use of these CLR services requires
additional language enhancements to C (enabled
by /clr) - New type categories
- Syntax for garbage collection
- All existing C code remains unchanged and
continues without behavioral changes
9Using Libraries
- Managed assemblies describe themselves with
metadata - Used instead of header files or type libraries
- C/CLI has the using directive using
ltSystem.Windows.Forms.dllgtusing
ltSystem.Xml.dllgtusing ltSystem.Data.dllgtusing
ltSystem.Web.dllgt - A source file can make use of several kinds of
librariesusing ltSystem.Data.dllgt // .NET
libraryimport ltmsxml4.dllgt // COM type
libraryinclude ltiostreamgt // Standard C
library
10New Type Categories
- New type categories provide specific semantics
needed for interoperating with other languages - Ref classes garbage collected, known to other
CLR languages - Value classes lightweight (fundamental types
like integers) - Native classes semantics and advantages of
native code even when compiling to MSIL - Types are declared with new spaced keywords
class N // // native ref class R
// // CLR reference type value class V
// // CLR value type interface class I
// // CLR interface type enum class E
// // CLR enumeration type
11Handles and gcnew
- C/CLI includes new syntax for first class
support of garbage collection - Pointers allow dynamic allocation on the native
heap - T t new T
- Pointers are stable (can be cast to int), even
during GC - Failure to explicitly call delete will leak
memory - Handles refer to objects on the CLR heap
- T t gcnew T
- Calling delete is optional
- Allocating on the stack continues to work
- T t
- Enables deterministic cleanup
- Managed types non-memory resources only
12Creating and using objects
1 Optional 2 Value types only
13Deterministic Destruction
- Nested usings in C are hard to read
using(SqlConnection conn new
SqlConnection(connString) ) // work
with the connection in some way
using(SqlCommand cmd new SqlCommand(queryString,
conn) ) // work with the
command // dont call Dispose or Close
14Deterministic Destruction
- Automatic scope is easier
- C destructor maps to CLR Dispose
- Both directions
- Less code, more control
SqlConnection conn(connString) // work
with the connection in some way SqlCommand
cmd(queryString, conn) // work with the
command // dont call Dispose or Close
15Three Ways to Use Managed Code
- Use .NET functionality in your application
- Take a new library and use it from your
application - Energize your application with a new look and
feel - Leverage new tools that generate code for WinFX
- Expose your functionality as .NET object model
- Expand your market to new language developers
- Take advantage of core performance of your
existing code - Use managed code as a extensibility model
- Add control and security to your extensibility
model - Make scripting as powerful as a general purpose
language
16Using Frameworks in Your Application
Your Application NowBuilt on top of native
libraries
New Application withAdded Functionality
Compile Pieceswith /clr
NativeLibraries
ManagedLibraries
Native Libraries
class Data gcrootltXmlDocumentgt
xmlDoc public void Load(stdstring
fileName) XmlTextReader reader
gcnew XmlTextReader(marshalltStringgt(fileName))
xmlDoc gcnew XmlDocument(reader)
17Using Frameworks in MFC
- Visual C 2005 allows you to use new Frameworks
libraries in MFC Applications - MFC includes many integration points
- MFC views can host Windows Forms controls
- Use your own Windows Forms dialog boxes
- MFC lets you use Windows Forms as CView
- Data exchange and eventing translation handled by
MFC - MFC handles command routing
- MFC applications will be able to take advantage
of current and future libraries directly with ease
18Exposing Functionality as .NET Objects
Add a new layerbuilt with /clr
Your Library Now
Managed API Layer
The Same Library
Native Libraries
Native Libraries
- Embed native pointers in managed types
- Use native types as method arguments and returns
ref class MyControl UserControl
stdvectorltstdstringgt words public void
Add(String s) Add(marshalltstdstringgt(s))
internal void Add(stdstring s)
words-gtpush_back(s)
19Real Customer example
Internet or Intranet
New Winforms appC or C/CLI
Legacy client appheavy MFC
New ASP.NET app C
Engine unmanaged C
DB
New wrapper C/CLI Compiled /CLR
DLL unmanaged C
DLL unmanaged C
DLL unmanaged C
20Real Customer example
Legacy client appno MFC
Engine unmanaged C
DB
DLL unmanaged C
DLL unmanaged C
DLL unmanaged C
21Real Customer exampleFirst try
Legacy client appno MFC Compile /CLR
New VSTO appsC
New dialogs and controls from WinForms library
Engine Compile /CLR
Base Class Libraries Free Functionality
DB
DLL Compile /CLR
DLL Compile /CLR
DLL Compile /CLR
22Real Customer exampleLater tries
Legacy client appno MFC Compile /CLR
New VSTO appsC
New dialogs and controls from WinForms library
Engine Compile /CLR
Engine unmanaged
DB
Base Class Libraries Free Functionality
DLL Compile /CLR
DLL unmanaged
DLL Compile /CLR
DLL unmanaged
23Placing the boundary
- Code that will be exposed to other runtime
components (e.g. C UI) - Write ref classes, compile /CLR
- Code that intends to call other managed code
(e.g. BCL) - Compile /CLR
- Code that is to be exposed to native and managed
components - Compile /CLR, native code calls as though it were
COM - Or compile native, managed code calls through C
Interop - Everything else
- Compile as native or /CLR to minimize transition
costs - Collaboration diagram
24Placing the boundary
C or C managed
C
CRT, STL, etc
One call to foo()
Hundreds of calls
C managed
C
CRT, STL, etc
One call to foo()
Hundreds of calls
C
C
CRT, STL, etc
C
One call
Hundreds of calls
One call to foo()
25To make your wrapper high performance
- Chunky is better than chatty
- Every transition costs
- Use a façade pattern
- Dont hurt the garbage collector
- Pinning pointers slows it
- Finalization really hurts it
- Dispose pattern is good
- Handy that destructors dispose
- Be aware of boxing
- Write explicit ToString or Equals overrides for
your value types - Be aware of marshalling
- Narrowing Unicode strings to ANSI may be more
expensive than just dealing with Unicode on the
unmanaged side - Dont pass values that wont be used
- If you control both sides, design an efficient
interface
26Verifiable C
- Essential for partial trust
- ClickOnce
- FullTrust includes SkipVerification
- Compile with /clrsafe to create a verifiable
assembly - Or get understandable error messages if its not
verifiable - No pointer arithmetic, not even
- Templates, deterministic destruction, other C
features no problem
27CLR Compilation Modes
- Four levels of CLR support are now available
- Mixed (/clr)
- Contains unmanaged and managed code
- Pure (/clrpure)
- Contains only managed code (pure MSIL)
- Can still use include and call native APIs
- Verifiable (/clrsafe)
- Contains only verifiable managed code
- Similar to C and Visual Basic assemblies
- Managed Extensions for C (/clroldSyntax)
- For compiling old-style code
- Set via project properties or command line
28Compilation Mode Relationships
29What C has that others dont
- Can generate native code
- C interop the fastest and easiest
- Deterministic destruction
- Templates and generics
- Optimized MSIL
- PGO for native and managed code
- .NET Linking
30Summary
- C/CLI is an elegant and useful way to create
managed applications in C - C programs benefit from .NET features
- .NET applications benefit from C features
- There are multiple ways to move onto the .NET
Framework while remaining a C developer
31Questions for me?
- Kate_at_gregcons.com
- www.gregcons.com/kateblog