Object с programming on windows

Creating an Object in COM

After a thread has initialized the COM library, it is safe for the thread to use COM interfaces. To use a COM interface, your program first creates an instance of an object that implements that interface.

In general, there are two ways to create a COM object:

  • The module that implements the object might provide a function specifically designed to create instances of that object.
  • Alternatively, COM provides a generic creation function named CoCreateInstance.

For example, take the hypothetical Shape object from the topic What Is a COM Interface?. In that example, the Shape object implements an interface named IDrawable . The graphics library that implements the Shape object might export a function with the following signature.

Given this function, you could create a new Shape object as follows.

The ppShape parameter is of type pointer-to-pointer-to- IDrawable . If you have not seen this pattern before, the double indirection might be puzzling.

Consider the requirements of the CreateShape function. The function must give an IDrawable pointer back to the caller. But the function’s return value is already used for the error/success code. Therefore, the pointer must be returned through an argument to the function. The caller will pass a variable of type IDrawable* to the function, and the function will overwrite this variable with a new IDrawable pointer. In C++, there are only two ways for a function to overwrite a parameter value: pass by reference, or pass by address. COM uses the latter, pass-by-address. And the address of a pointer is a pointer-to-a-pointer, so the parameter type must be IDrawable** .

Here is a diagram to help visualize what’s going on.

The CreateShape function uses the address of pShape ( &pShape ) to write a new pointer value to pShape.

CoCreateInstance: A Generic Way to Create Objects

The CoCreateInstance function provides a generic mechanism for creating objects. To understand CoCreateInstance, keep in mind that two COM objects can implement the same interface, and one object can implement two or more interfaces. Thus, a generic function that creates objects needs two pieces of information.

  • Which object to create.
  • Which interface to get from the object.

But how do we indicate this information when we call the function? In COM, an object or an interface is identified by assigning it a 128-bit number, called a globally unique identifier (GUID). GUIDs are generated in a way that makes them effectively unique. GUIDs are a solution to the problem of how to create unique identifiers without a central registration authority. GUIDs are sometimes called universally unique identifiers (UUIDs). Prior to COM, they were used in DCE/RPC (Distributed Computing Environment/Remote Procedure Call). Several algorithms exist for creating new GUIDs. Not all of these algorithms strictly guarantee uniqueness, but the probability of accidentally creating the same GUID value twice is extremely small—effectively zero. GUIDs can be used to identify any sort of entity, not just objects and interfaces. However, that is the only use that concerns us in this module.

For example, the Shapes library might declare two GUID constants:

(You can assume that the actual 128-bit numeric values for these constants are defined elsewhere.) The constant CLSID_Shape identifies the Shape object, while the constant IID_IDrawable identifies the IDrawable interface. The prefix «CLSID» stands for class identifier, and the prefix IID stands for interface identifier. These are standard naming conventions in COM.

Given these values, you would create a new Shape instance as follows:

The CoCreateInstance function has five parameters. The first and fourth parameters are the class identifier and interface identifier. In effect, these parameters tell the function, «Create the Shape object, and give me a pointer to the IDrawable interface.»

Set the second parameter to NULL. (For more information about the meaning of this parameter, see the topic Aggregation in the COM documentation.) The third parameter takes a set of flags whose main purpose is to specify the execution context for the object. The execution context specifies whether the object runs in the same process as the application; in a different process on the same computer; or on a remote computer. The following table shows the most common values for this parameter.

Читайте также:  Мои расходы для mac os
Flag Description
CLSCTX_INPROC_SERVER Same process.
CLSCTX_LOCAL_SERVER Different process, same computer.
CLSCTX_REMOTE_SERVER Different computer.
CLSCTX_ALL Use the most efficient option that the object supports. (The ranking, from most efficient to least efficient, is: in-process, out-of-process, and cross-computer.)

The documentation for a particular component might tell you which execution context the object supports. If not, use CLSCTX_ALL. If you request an execution context that the object does not support, the CoCreateInstance function returns the error code REGDB_E_CLASSNOTREG. This error code can also indicate that the CLSID does not correspond to any component registered on the user’s computer.

The fifth parameter to CoCreateInstance receives a pointer to the interface. Because CoCreateInstance is a generic mechanism, this parameter cannot be strongly typed. Instead, the data type is void**, and the caller must coerce the address of the pointer to a void** type. That is the purpose of the reinterpret_cast in the previous example.

It is crucial to check the return value of CoCreateInstance. If the function returns an error code, the COM interface pointer is invalid, and attempting to dereference it can cause your program to crash.

Internally, the CoCreateInstance function uses various techniques to create an object. In the simplest case, it looks up the class identifier in the registry. The registry entry points to a DLL or EXE that implements the object. CoCreateInstance can also use information from a COM+ catalog or a side-by-side (SxS) manifest. Regardless, the details are transparent to the caller. For more information about the internal details of CoCreateInstance, see COM Clients and Servers.

The Shapes example that we have been using is somewhat contrived, so now let’s turn to a real-world example of COM in action: displaying the Open dialog box for the user to select a file.

The Component Object Model

The Microsoft Component Object Model (COM) is a platform-independent, distributed, object-oriented system for creating binary software components that can interact. COM is the foundation technology for Microsoft’s OLE (compound documents), ActiveX (Internet-enabled components), as well as others.

To understand COM (and therefore all COM-based technologies), it is crucial to understand that it is not an object-oriented language but a standard. Nor does COM specify how an application should be structured; language, structure, and implementation details are left to the application developer. Rather, COM specifies an object model and programming requirements that enable COM objects (also called COM components, or sometimes simply objects) to interact with other objects. These objects can be within a single process, in other processes, and can even be on remote computers. They can be written in different languages, and they may be structurally quite dissimilar, which is why COM is referred to as a binary standard; a standard that applies after a program has been translated to binary machine code.

The only language requirement for COM is that code is generated in a language that can create structures of pointers and, either explicitly or implicitly, call functions through pointers. Object-oriented languages such as C++ and Smalltalk provide programming mechanisms that simplify the implementation of COM objects, but languages such as C, Java, and VBScript can be used to create and use COM objects.

COM defines the essential nature of a COM object. In general, a software object is made up of a set of data and the functions that manipulate the data. A COM object is one in which access to an object’s data is achieved exclusively through one or more sets of related functions. These function sets are called interfaces, and the functions of an interface are called methods. Further, COM requires that the only way to gain access to the methods of an interface is through a pointer to the interface.

Besides specifying the basic binary object standard, COM defines certain basic interfaces that provide functions common to all COM-based technologies, and it provides a small number of functions that all components require. COM also defines how objects work together over a distributed environment and has added security features to help provide system and component integrity.

The following topics in this section describe basic COM issues related to designing COM objects:

Overview of Windows Programming in C++

There are several broad categories of Windows applications that you can create with C++. Each has its own programming model and set of Windows-specific libraries, but the C++ standard library and third-party C++ libraries can be used in any of them.

This section discusses how to use Visual Studio and the MFC/ATL wrapper libraries to create Windows programs. For documentation on the Windows platform itself, see Windows documentation.

Command line (console) applications

C++ console applications run from the command line in a console window and can display text output only. For more information, see Create a console calculator in C++.

Native desktop client applications

A native desktop client application is a C or C++ windowed application that uses the original native Windows C APIs or Component Object Model (COM) APIs to access the operating system. Those APIs are themselves written mostly in C. There’s more than one way to create a native desktop app: You can program using the Win32 APIs directly, using a C-style message loop that processes operating system events. Or, you can program using Microsoft Foundation Classes (MFC), a lightly object-oriented C++ library that wraps Win32. Neither approach is considered «modern» compared to the Universal Windows Platform (UWP), but both are still fully supported and have millions of lines of code running in the world today. A Win32 application that runs in a window requires the developer to work explicitly with Windows messages inside a Windows procedure function. Despite the name, a Win32 application can be compiled as a 32-bit (x86) or 64-bit (x64) binary. In the Visual Studio IDE, the terms x86 and Win32 are synonymous.

To get started with traditional Windows C++ programming, see Get Started with Win32 and C++. After you gain some understanding of Win32, it will be easier to learn about MFC Desktop Applications. For an example of a traditional C++ desktop application that uses sophisticated graphics, see Hilo: Developing C++ Applications for Windows.

C++ or .NET?

In general, .NET programming in C# is less complex, less error-prone, and has a more modern object-oriented API than Win32 or MFC. In most cases, its performance is more than adequate. .NET features the Windows Presentation Foundation (WPF) for rich graphics, and you can consume both Win32 and the modern Windows Runtime API. As a general rule, we recommend using C++ for desktop applications when you require:

  • precise control over memory usage
  • the utmost economy in power consumption
  • usage of the GPU for general computing
  • access to DirectX
  • heavy usage of standard C++ libraries

It’s also possible to combine the power and efficiency of C++ with .NET programming. You can create a user interface in C# and use C++/CLI to enable the application to consume native C++ libraries. For more information, see .NET Programming with C++/CLI.

COM Components

The Component Object Model (COM) is a specification that enables programs written in different languages to communicate with one another. Many Windows components are implemented as COM objects and follow standard COM rules for object creation, interface discovery, and object destruction. Using COM objects from C++ desktop applications is relatively straightforward, but writing your own COM object is more advanced. The Active Template Library (ATL) provides macros and helper functions that simplify COM development. For more information, see ATL COM desktop components.

Universal Windows Platform apps

The Universal Windows Platform (UWP) is the modern Windows API. UWP apps run on any Windows 10 device, use XAML for the user-interface, and are fully touch-enabled. For more information about UWP, see What’s a Universal Windows Platform (UWP) app? and Guide to Windows Universal Apps.

The original C++ support for UWP consisted of (1) C++/CX, a dialect of C++ with syntax extensions, or (2) the Windows Runtime Library (WRL), which is based on standard C++ and COM. Both C++/CX and WRL are still supported. For new projects, we recommend C++/WinRT, which is entirely based on standard C++ and provides faster performance.

Desktop Bridge

In Windows 10, you can package your existing desktop application or COM object as a UWP app, and add UWP features such as touch, or call APIs from the modern Windows API set. You can also add a UWP app to a desktop solution in Visual Studio, and package them together in a single package and use Windows APIs to communicate between them.

Visual Studio 2017 version 15.4 and later lets you create a Windows Application Package Project to greatly simplify the work of packaging your existing desktop application. A few restrictions apply to the registry calls or APIs your desktop application can use. However, in many cases you can create alternate code paths to achieve similar functionality while running in an app package. For more information, see Desktop Bridge.

Games

DirectX games can run on the PC or Xbox. For more information, see DirectX Graphics and Gaming.

SQL Server database clients

To access SQL Server databases from native code, use ODBC or OLE DB. For more information, see SQL Server Native Client.

Windows device drivers

Drivers are low-level components that make data from hardware devices accessible to applications and other operating system components. For more information, see Windows Driver Kit (WDK).

Windows services

A Windows service is a program that can run in the background with little or no user interaction. These programs are called daemons on UNIX systems. For more information, see Services.

SDKs, libraries, and header files

Visual Studio includes the C Runtime Library (CRT), the C++ Standard Library, and other Microsoft-specific libraries. Most of the include folders that contain header files for these libraries are located in the Visual Studio installation directory under the \VC\ folder. The Windows and CRT header files are found in the Windows SDK installation folder.

The Vcpkg package manager lets you conveniently install hundreds of third-party open-source libraries for Windows.

The Microsoft libraries include:

Microsoft Foundation Classes (MFC): An object-oriented framework for creating traditional Windows programs—especially enterprise applications—that have rich user interfaces that feature buttons, list boxes, tree views, and other controls. For more information, see MFC Desktop Applications.

Active Template Library (ATL): A powerful helper library for creating COM components. For more information, see ATL COM Desktop Components.

C++ AMP (C++ Accelerated Massive Parallelism): A library that enables high-performance general computational work on the GPU. For more information, see C++ AMP (C++ Accelerated Massive Parallelism).

Concurrency Runtime: A library that simplifies the work of parallel and asynchronous programming for multicore and many-core devices. For more information, see Concurrency Runtime.

Many Windows programming scenarios also require the Windows SDK, which includes the header files that enable access to the Windows operating system components. By default, Visual Studio installs the Windows SDK as a component of the C++ Desktop workload, which enables development of Universal Windows apps. To develop UWP apps, you need the Windows 10 version of the Windows SDK. For information, see Windows 10 SDK. (For more information about the Windows SDKs for earlier versions of Windows, see the Windows SDK archive).

Program Files (x86)\Windows Kits is the default location for all versions of the Windows SDK that you’ve installed.

Other platforms such as Xbox and Azure have their own SDKs that you may have to install. For more information, see the DirectX Developer Center and the Azure Developer Center.

Development Tools

Visual Studio includes a powerful debugger for native code, static analysis tools, graphics debugging tools, a full-featured code editor, support for unit tests, and many other tools and utilities. For more information, see Get started developing with Visual Studio, and Overview of C++ development in Visual Studio.

Читайте также:  Windows phone как веб камера
Оцените статью