In this first chapter, I cover the basic features of the Managed Extensions. I start by explaining how to develop managed types and how these differ from unmanaged types, both in their declaration and their use. I cover how to use managed arrays, interfaces, and exceptions. C++ written with the Managed Extensions follows the .NET model rather than the C++ model in terms of inheritance and casts, so I conclude this chapter by describing how .NET differs from unmanaged C++ in these respects.
One of the reasons for using C++ is that it allows you to use existing unmanaged code in your .NET projects. The Managed Extensions compiler has a technology quaintly called It Just Works! (IJW). This technology allows you to use unmanaged libraries in managed projects and to intermingle managed and unmanaged classes. In this chapter, I tell you how to you use IJW and give some insights into how it works. .NET also has an attribute-based technology called platform invoke that allows any .NET-enabled language to access code exported from a DLL. I explain how you can use platform invoke and describe how you can customize the marshaling it performs. A variation of platform invoke is COM interop, which is the final subject of this chapter. COM interop allows managed code to use COM objects as if they were .NET objects, and it allows unmanaged code to use .NET objects as if they were COM objects. I go over how COM interop works and how you can register classes and generate the attributes required by COM interop.
Delegates and Events
Function pointers are useful in unmanaged projects because they allow function binding to be performed at runtime rather than at compile time. C++ virtual functions and COM interfaces are based on function pointers, and function pointers also enable you to define notification systems. .NET has its own version of function pointers—called delegates—that are type-safe, eliminating one big disadvantage of unmanaged function pointers: namely, casting between function pointer types. In this chapter, I show you how to use delegates with C++, how this approach compares with unmanaged function pointers, and how you can use delegates with unmanaged code. I also explain how to make asynchronous calls through delegates (using a system-provided thread) and talk about how to write multithreaded code with .NET. Finally, I clarify how .NET uses delegates to implement a formal notification mechanism called .NET events.
User Interface Development
The .NET Framework augments Windows with a new graphics library called GDI+. This is an unmanaged library, but the .NET Framework comes with .NET wrapper classes. The windowing technology in .NET is called Windows Forms. You can draw on a form with GDI+, and you can use a form as a container for controls. In this chapter, I explain how you can create GUI applications in C++ with Windows Forms and describe how to implement such applications using Win32 windows. I also show how to handle Windows messages through .NET events and how to bypass this mechanism to get the most control over a window’s behavior. I also go over how to use managed resources and native resources efficiently in a managed class so that resources are released when your application no longer needs them. Finally, I define “managed” resources and explain how to add one to your application, and discuss how to localize resources.
In this chapter, I delineate how .NET code is stored in executable files. I start by explaining the format of .NET assemblies and describing how they are implemented as Win32 portable executable (PE) files. I then discuss how you can get information about .NET metadata and code within an assembly by using COM objects the .NET Framework supplies. The .NET runtime is implemented with unmanaged code, and Microsoft has designed the runtime so that unmanaged code can get access to the runtime through COM objects. In this chapter, I explain how to use these objects to access and configure the runtime from unmanaged code and how to instruct the runtime to run managed code. A managed application can be configured through an XML file associated with the application. The runtime reads the configuration file when the application starts so that it can get information about the facilities that the application requires. One of the big advantages of the runtime is that it will load only the libraries that your application was specifically built to use. You can configure the rules that the runtime uses to locate those libraries via the configuration file. Your code can also access the information in a configuration file, and in this chapter, I show you how to do this and how to extend configuration files and the API to read them. Finally, I describe code access security and demonstrate how to use it in your code. I also show the default permissions that are required by .NET code written with Managed Extensions for C++.
Building Code with Visual C++.NET
Visual Studio .NET is a mixed managed and unmanaged application that integrates various application-development tools. In this chapter, I explain how you can use the environment to develop your projects. I cover the facilities of the editor and the tools that are provided to allow you to manage your projects. I talk about the Visual Studio .NET project wizards and the types of C++ projects that you can develop. I conclude the chapter with examples of the types of managed projects that you can develop and describe how to customize the code provided by the project wizard.
The last stage of your development cycle is typically the testing stage: you need to test the project to ensure that it works the way you intend it to, and when it does not work as expected, you will need to debug the code to determine where the problem lies. Although the testing stage often comes at the end of a development cycle, you can save yourself a lot of effort by writing code up front that provides diagnostic information. In this chapter, I describe the facilities that the .NET Framework offers to allow you to diagnose problems in your code and explain how you can collect this diagnostic information. Visual Studio .NET has an integrated managed and native code debugger, so once you have identified a problem you can step through your code to pinpoint the source. I explain how to use the debugger and its various facilities. I also talk about the special issues you need to consider when debugging multithreaded code and applications that consist of more than one process. Finally, I show you how to profile code. Visual Studio .NET does not provide a code profiler, but the .NET Framework has support for providing profiling information through a user-supplied COM object. I give an example of such a profiling object.
.NET Framework Libraries
The .NET Framework class library is very comprehensive, and you’ll find code in it to perform just about any task you could do previously with the C runtime library (CRT) or the standard C++ library. In this appendix, I present, in a series of tables, the .NET code that is equivalent to the most useful CRT functions and standard library classes. The intention of this appendix is to provide a starting point for when you ask the inevitable question, "How do I do this in .NET?"
This appendix is a personal list of further resources. This list is not exhaustive, and I am sure that it is not the best list of .NET resources. However, I have provided the resources that were particularly useful to me, and I hope that you’ll benefit from them too.