Chapter 5 DirectX Foundation and Horror COM

xiaoxiao2021-03-06  29

Chapter 5 DirectX Foundation and Horror COM this chapter, we will conduct in-depth research on DirectX and the basic components that make up this unbelievable technology. In addition, we will learn more about the foundation of the DirectX components of COM. If you are a simple C programmer, you have to pay attention, but don't worry too much, I will give you a very thoughtful.

However, in this chapter, it is still necessary to warn before you plan to skip this chapter. DirectX is closely linked to COM. It is difficult to explain the other party without mentioning one party. As if, how can you explain the "zero" without giveing ​​the definition of "zero"? If you think it is easy to get from COM, it is easy to talk about DirectX.

Below is a list of the main contents we will discuss: • DirectX Introduction · Component Object Model (COM) · A COM implementation can operate, how DirectX and COM are coordinated, COM's future]

DirectX found these days I felt that I was like a satellite of Microsoft (reminding Microsoft, giving me money), trying to drag all my friends into the dark side. But Microsoft This bad guy has a better technology! Am i right? What do you think Microsoft is, an empire star destroyer or half a rebellious person? See what I am talking about.

DirectX may further weaken the programmer's control, but in fact it is worth it. It is basically an abstract video, audio, input, network, installation, and system software for more features. Therefore, you can drive any specific PC hardware with the same code without the use of how these hardware is set. In addition, DirectX technology is better than Windows GDI and / or MCI (Media Control Interface), and it is more functions.

Figure 5.1 illustrates how you applies and do not apply DirectX to create a game. Note that the DirectX solution is more simple and elegant. Understand how DirectX works? It provides access to all equipment almost hardware levels. Realizing this access depends on a technology called component object model and a series of drivers and library functions written by Microsoft and hardware production. Microsoft offers a range of standardized protocols for functions, variables, data structures, etc., and hardware manufacturers must comply with these discussions when implementing drivers communicating with hardware.

As long as these agreements are all subjective, you don't need to worry about the details of the hardware. You just need to call DirectX, it will give you a detail for you. Regardless of the graphics, sound card, input devices, network cards, or any other devices, as long as DirectX support, your program can use the device without knowing the device.

Currently, DirectX includes many components. They are listed in Figure 5.2. · DirectDraw (DirectX8.0 and above no longer have) · DirectSound · DirectSound3D · DirectMusic · DirectInput · DirectPlay · DirectSeup · Direct3DRM · Direct3dIM · DirectX Graphics (merged DirectDraw / Direct3D) · DirectX Audio (merged DirectSound / DirectMusic) · When DirectShow is released, Microsoft decides to merge DirectDraw and Direct3D together, all integrated into DirectX Graphics. The result is that DirectDraw is removed in DirectX8.0. But you can still use DirectDraw, just in DirectX8.0, it is not upgraded. In addition, DirectSound and DirectMusic are also integrated into DirectX Audio. Finally, DirectShow is integrated into DirectX. The guy of Microsoft is really busy. These changes may seem to have a hard and confusing, but DirectX cool is as long as we think, you can use DirectX3.0 or 5.0 or 6.0, or others. Worship COM (immediately we will learn it), we can use any version we want and in line with our needs, this is completely dedicated to us. And in our opinion, version 7.0 and part of 8.0 have enough. Further, if you are familiar with a version of DirectX, you are familiar with all the versions, the syntax may change, the interface is more functional, but in turn, the nature is the same. The only change is the biggest Direct3D, but we don't plan to discuss this book. Essentially, we will only discuss game programming. Yes, there are two books on the book CD, one of which is about 3D, another about Direct3D, but in this book we will only focus on DirectX's backbone, so you will learn enough you to do it. Game related knowledge. Of course, from your entire game programming career seems to be less than this, but when you want to use other API, you will still understand the essence of the game programming technology, which is the ultimate goal of this book writing.

Hardware Analog Layers (HAL) and Hardware Abstract Layers (HAL) are in Figure 5.2, you may notice that there are two hierarchies that are called HEL (hardware analog layers) and HAL (hardware abstraction layers) under DirectX. DirectX is designed to be very far away, it assumes that advanced features have been implemented by hardware. However, what happens if the hardware does not support these features? This is the origin of Hal and Hel.

Hal, or the hardware abstraction layer is a Hardware-oriented (To the Metal), it is directly dialogue with hardware. This layer is usually composed of drivers provided by hardware vendors, and you can call with it through a general DirectX function. Briefly, when your request is supported by hardware, it will use HAL to achieve the purpose of acceleration. For example, if you ask a bitmap, you will complete the task by hardware instead of software.

Hel, or hardware simulation layer. When the hardware does not support a certain feature you request, it will use it. For example, you asked the graphics to rotate a bitmap. If the hardware does not support rotation, Hel intervene and use the software algorithm to complete. Obviously, the speed will be slow, but the focus is despite slow point but your program is not interrupted. In addition, the switch between HAL and HEL is transparent to you. If you call DirectX to do something, as long as the hardware can do it directly by Hal, otherwise he will call HEL's software simulation to complete the task. Now, you may think, is it a bit too much in the level of software. This is a problem. But the fact is that DirectX is very concise, so that you use the only price you pay may be one or two additional function calls. This cost is small for 2D / 3D drawing, network, and audio acceleration. Can you imagine how to write drivers for each graphics card on the market? I believe me, even if you spend thousands of years, you can't finish this. DirectX is provided by Microsoft and hardware vendors to your high quality and powerful publishing engine.

In-depth understanding of the DirectX underlying component now let us browse DirectX's components and their features:

DirectDraw: This is the main control graphics card to render and 2D drawing engines. Any drawing must be done via it, so it may be the most important one in all components of DirectX. The DirectDraw object represents the graphics card in your system. DirectDraw is already unavailable in DirectX8.0, so we need to use it to use DirectX7.0 interface.

DirectSound: This is the audio component of DirectX. It only supports digital audio without supporting MIDI. But the component allows you to use third-party audio systems for you to make sounds. This can make your life 100 times more. Audio programming is a black art, even in the past, no one is willing to write drivers for all sound cards. Although some vendors offer such as Miles Sound System and Diamondware Sound Toolkit audio. Both are a powerful system that allows you to simply load, play numbers or MIDI audio for your DOS or WIN32 program. However, there is DirectSound, DirectSound3D, and the nearest DirectMusic component, there is no need to use the third party library.

DirectSound3D: This is the 3D audio component of DirectSound. It allows you to locate the 3D source in a space, just like the source is floating in the room. This is a very new technology, but it has developed very quickly. Today, most sound cards support 3D effect hardware acceleration, including Doppler Shift, refraction, reflection, and more. However, if the software simulation, these hardware acceleration functions will not be available.

DirectMusic: DirectX recently added. Thank you! DirectMusic is the MIDI technology that is missing by DirectSound. But more than this, DirectMusic has a new DLS system. The system allows you to create a number of devices and play with MIDI control. This is very like a sound wave synthesizer, but is a software method. DirectMusic has a new intelligent performance engine. In real-time systems, the engine changes your music via the template you provide. Importantly, DirectMusic can create music in the popular music format. Is it strong?

DirectInput: This system processes all equipment inputs, including mouse, keyboard, rocker, handle, rolling, and so on. Now it also supports feedback equipment (consisting of electromechanical motor and force sensors, let you feel the real power).

DirectPlay: This is the network part of DirectX. It allows you to build abstract connections by using Internet, Moden, Direct Cable Connection, or any other future connecting media. DirectPlay is that it allows it to establish connections without knowing the network. You don't need to write drivers, use sockets or something similar. In addition, DirectPlay supports the game in the game in progress and players with game halls with gathering and games. DirectPlay does not force you to obey the multiplayer online game architecture. Everything what it does is to send and accept the message package for you, look at the contents and check whether you are valid for you. Direct3DRM. This is the retention mode of Direct3D. A advanced, object-based 3D system. You can use it to create basic 3D programs. Although it utilizes 3D acceleration but running speed is not the fastest. It is very suitable for Demo, model, model, or quite slow.

Direct3Dim: This is the real-time mode of DirectX. Low-level 3D support in DirectX. At first, it was extremely difficult to use and there were many conflicts with OpenGL. Old instant mode uses a technology called execution buffer, basically, is the array of data and instructions you created, using the technology drawing. However, since DirectX5.0, instant mode supports many OpenGL interfaces through the DrawPrimitive () function. It allows you to send triangles and sectors to the rendering engine and call function calls through the function call to change their status without using the execution cache. So I now like DirectX3D instant mode. Although this volume and the second volume are software-based 3D game books, I will still discuss D3DIM at the end of the volume II for integrity. In fact, there is an e-book that is completely about DirectX3D instant mode on the second volume.

DirectSetup / AutoPlay: This is allowed to install DirectX from your application in your app and directly launch the game directly after the CD disc is inserted. DirectSetup is a small function set. This function is set to load DirectX's runtime files on the client and register these files in the registry. AutoPlay is a standard CD subsystem that looks for the autoplay.inf file under the root directory of the CD. If you find the file, AutoPlay executes the batch command in the file.

DirectX Graphics: In order to enhance performance, Microsoft decides to combine DirectDraw and DirectX3D to integrate the functionality of DirectDraw and DirectX3D in the 2D field. I personally don't think that DirectDraw should be removed, not only because there are many software to use it, but more importantly, using DirectX3D to do 2D drawing is a painful thing, it will kill a lot of essential should be 2D Apps, such as GUI applications, and similar games. But no matter what, we don't have to worry too much. After all, we can still use the DirectX7.0 interface DirectDRAW.

Directaudio: This fusion is much smaller than DirectX Graphics. Here, DirectSound and DirectMusic are more closely integrated, without anything removal from it. DirectMusic is very weak in DirectX7.0, completely based on COM, and cannot be accessed via DirectSound. In Directaudio, these weaknesses are changed. As long as you are willing, you can use them together.

DirectShow: This component is applied to streaming of Windows platforms. DirectShow provides high quality video capture and playback of multimedia streams. It supports numerous formats, including ASF, MPEG, AVI, MP3, and WAV files. It supports devices using Windows Drive Models (WDM) or video capture of video devices for Windows. DirectShow is integrated with other technologies of DirectX. As long as the hardware allows, it will automatically detect and use video and hard disk hardware, but it also supports not using hardware acceleration. This makes things easier, because the past When you want to play some videos in a game, you must use the third party library or write code yourself. When these are integrated into DirectX, huh, it is really great. The only problem is that it is too advanced, so it is a bit painful to set up and use it. Finally, you may want to know about the relevant situation of all version of DirectX. This review may spend the first half of the year. Yes, to a large extent, the industry we have is a big adventure, the development of drawing and game technology is too fast. However, since DirectX is COM technology, you write, such as DirectX3.0-based programs that ensure that you can run on DirectX8.0. Let's take a look at how it is running ...

COM: Is it a masterpiece of Microsoft or the masterpiece of the devil? Today's computer program is easy to reach millions of rows. The large system is more easily reaching billions. As the program grows, abstract and inheritance appears extremely important. Otherwise, complete confusion is definitely coming. This confusion is just like a customer service of the telephone company.

The most recent two object-oriented programming techniques are used to computer language attempts to C and Java. C is actually C's object-oriented evolution (or more likely to return) {translator: in parentheses, unclear why this} On the other hand, Java is based on C , but it fully objects and Very simple. In addition, Java is a platform and C is a language.

In short, the language is great. But how do you use them to spend a long time. Many people are still useless or incorrectly used even if C has a rich and powerful OO (object-oriented) feature. It is still a bitter problem that is still a bitter problem. And this is one of the difficulties of COM intending.

COM is a new software specification from zero. How much work principle is a bit like a computer chip or a tall toy {translator: a toy similar to building blocks}, to make them work, you only need to simply Plug them together. Every chip and toys know how to do a chip or toy (because their interface is well defined). To achieve this software technology, you need an interface that is unified for any function set you can imagine. These are good things for COM.

A cool aspect of the computer chip is that when you add a chip in the design, you don't need to tell other chips you have made some changes. If you know, it is difficult to do this in software programming. You must recompile at least. Solving this problem is another goal of COM. You should be able to add new features to a COM object without destroying software using old COM objects. In addition, COM objects can be changed without recoiling source programs. Cool.

Since you can upgrade your COM object without recompile your program, this means you can upgrade your software without publishing patches and new versions. For example, you have a program that uses three COM objects: an implementation drawing, a hard disk, and an implementation network (see Figure 5.3). Now I promise you to sell 100,000 copies of the program, but you don't plan to post 100,000 patchs! To upgrade the COM object responsible for the drawing, all your work you do is to give the user a new COM object that is responsible for drawing, and then the program will use it. No need to compile, no need to link, don't do anything. Simple. Of course, this role is quite complicated in low-level levels. If you want to write your own COM object, it is very challenging, but it is very simple to use them. Figure 5.3. The next question next question is: How is COM organized to have this type of attribute? The answer is that there is no rule in COM, but in most cases, the COM object is DDL downloaded or provided with the program, or a dynamic link library. This can be easily updated and changed. The only problem is to use COM's programs must know how to load COM objects from a DLL. However, we will discuss this issue again in the later "Construction of the Quasi-COM Object". What is the COM object? A COM object is actually a C class, or a series of C classes for many interfaces. (Basically, an interface is a series of functions) These interfaces are used to communicate with COM objects. Look at Figure 5.4. Here we see a COM object called Igraphics, ISound, and Iinput, respectively. Figure 5.4 Interface of a COM object has a better (when you know how to call) the function. This simple COM object has one or more interfaces, and you can have one or more COM objects. Further, the COM specification requires any interfaces you created to be derived from a special base class called iUnknown. If you are a C programmer, these means that the IunkNown object is a starting point for building an interface. Let's take a look at the definition of the IunkNown class: struct iunknown {

// this function is buy r et ot in q qert (const same) ip) = 0;

// this is used to increment interfaces Reference Countvirtual ulong __stdcall addressf () = 0;

// this is buy to decrement interfaces Reference Countvirtual ulong __stdcall release () = 0;

}; Note: All methods are virtual functions. In addition, the method uses __stdcall, which means the use of standard C / C parameters into the stack order. Maybe you still remember the "Windows Programming Model" in the second chapter "said __stdcall from right to left the parameters in the stack.

Even if you are a C programmer, if you are more sparsely for virtual functions, this class definition may make you confused. In short, let's analyze this iUnknown, see what is in the end. All interfaces inherited from IunkNown should be implemented, at least queryinterface (), addRef (), and release (), you have to implement it.

Further, a rule of COM is if you have an interface, you should access any other interface through this interface, as long as these interfaces are from the same COM object. Basically, this means you can come anywhere anywhere. Look at Figure 5.5. Figure 5.5 Switching skills between the interfaces in COM objects: usually do not need to call AddRef () on the interface or COM object. It is built into the function queryinterface (). But sometimes you have to increase the number of COM objects to make COM objects to make more about the object's reference, then you have to call this function. AddRef () is an interesting function. The COM object uses a reference to the reference count (Reference Counting) to track your usage. This technique is used in the requirements of the COM specification rather than programming language characteristics. Thus, when a COM object is established and an interface for retrieving how many times a number of references to this object is established, add ADDREF (). If the COM object is established with malloc () or new [], this is the C / C language characteristic, and the object is destroyed when the reference count is reduced to 0.

COM objects are C classes. This fact also brought us another problem. How do I create and use them in VB, Java, ActiveX, etc.? Oh, that is just very happening, COM designer uses the VC class to implement COM, but you don't have to use C to access COM, and even do not need to use C to create COM. As long as you create a binary form that creates a VC class with a Microsoft C compiler, that COM object will be com-compliant. Of course, most compiler products include accessories or tools to help generate COM objects, so this is not a big problem. What is better about this problem is that you can write a COM object with C , VB or Delphi, then this COM object can be used by any language! The binary form in memory is always the same.

Release () is used to reduce references to a COM object or interface. In most cases, when you use an interface, you have to call this function. At some point, if you have created an object and then create another object in this object, the release () of the parent object will be called the sub-object or the delease object (). However, call Release () is a good idea in the order of access order.

For more information on interface ID and GUID, as I mentioned earlier, each COM object and interface must have a unique 128-bit identifier for requesting and access. This number is generally called GUID (globally unique identifier). Specifically, when the COM interface is defined, the interface has an interface ID or the IID. To generate these IDs you need to use a program written by Microsoft (or a similar program written with the same algorithm), Figure 5.6 shows Guidgen.exe. Figure 5.6 Guidgen.exe What you have to do is to choose an ID type you want (there are four different formats), then the program generates a 128-bit vector that is guaranteed to be generated again on any machine at any time. . Look like? of course not. This is just the sense of mathematics and probability. In short, if you use, don't ask "Why" and ask.

When you have a GUID or IID, these IDs are on your clipboard, you can paste it into your program. Below is an example of IID II II in this section: // {C1BCE961-3E98-11D2-A1C2-004095271606} static const << name >> = {0xC1BCE961, 0x3E98, 0x11d2, {0xA1, 0x11, 0x0, 0x40, 0x95, 0x27, 0x16, 0x6}}; of course, << name >> Replaces you in your program in your program. You can understand what I am talking about. GUID and IID are used to reference COM objects and their interfaces. So, whenever you create a new COM object and a series of interfaces, these numbers are the only thing you need to give those programmers who want to use the COM object. Once they get IID, they can create COM objects and interfaces.

Creating a class COM object Creating a full-featured COM object will greatly beyond the scope of this book. You just need to know how to use them. But if you like the root of the roots like I, we have to do this is to create a very basic COM object, as an example, to help you answer some questions.

Ok, you know that all COM objects have a series of interfaces, and all COM objects must be derived from an iUnknown class. Then, once you have established all the interfaces, you will put them in a container class, and then implement all things. For example, let's create a COM object containing three interfaces, and the three interfaces are: isound, Igraphics, and IINPUT. You may define them like this: // graphics interface struct iographics: iUnknown {Virtual Int Initgraphics (int MODE) = 0; Virtual Int setPixel (int X, int y, int c) = 0; // Other methods .. };

// Sound interface struct isound: iUnknown {Virtual int initsound = 0; Virtual Int Plays = 0; // Other methods ...};

// INPUT interface struct input: iUnknown {virtual int initInput (int custom) = 0; Virtual int = 0; // Other methods ...};

Now you have defined all interfaces, let's create container classes, which is the core of COM objects:

Class CT3D_ENGINE: PUBLIC IGRAPHICS, ISOOND, IINPUT {public:

/ / Realize IUNKNOWNVIRTUAL HRESULT __STDCALL Queryinterface here (Const IID & IID, (Void **) IP) {/ * real importation * /}

// this method increases the interfaces Reference Countvirtual ulong __stdcall addref () {/ * real importation * /}

// this method Decreases the interfaces Reference Countvirtual Ulong __stdcall release () {/ * real importation * /}

// Note TheRe Still ISN't a method to create one of these // Objects ... // now implements each interface.

// ibraphicsvirtual int initgraphics (int mode) {/ * importation * /} Virtual Int setPixel (int X, int y, int c) {/ * importation * /}

// isoundvirtual int initsound (int DRIVER) {/ * importation * /} Virtual Int Plays (int Note, int vol) {/ * importation * /}

// IINPUTVIRTUAL INT InitInput (int device) {/ * implemementation * /}

Virtual Int ReadStick (int Stick) {/ * usmentation * /}

Private:

// .. locals

}

Note: Do you still yearning for a generic way to create a COM object? This is undoubtedly a problem. There are many ways to do in the COM specification, but there is no one to link implementations and specific platforms or languages. A simple way to do this is to create a function called CocreateInstance () or COMCREATE () to create an IUNKNOWN for initialization instance objects. This function often loads a DLL containing COM code and then runs from the code. Once again, this technology exceeds you need to know, I just throw this technology to you, you will be disposed. I will skip these and continue our discussion with this example.

From this example you can see that the COM interface and its encoding have nothing to do in addition to usual C virtual classes. But the real COM object is to be properly encoded and registered here, and add a number of necessary rules. But at least, they are clasped with methods, function pointers or other things (or if you are C programmer, structure). In short, let us conduct a concise tracetrans to review your knowledge about COM.

COM's brief description COM is a new method for writing software components. It allows you to create a dynamic link to the software module that can be reused. Each COM object has one or more interfaces that do actual work. These interfaces are just a collection of functions for methods or via virtual functions. (More introduction in the next chapter)

Since GUID is used, each COM object and interface are uniquely identified. Of course, you have to generate a GUID for your COM object. You use the GUID or IID to access the COM object, interface, and share COM objects and interfaces with other programmers.

If you create a new COM object to upgrade the old, you must implement the old interface with the new interface. This is a very important principle: all COM object-based procedures do not require recompilation, still running normally under the new version of COM objects.

COM is a general technical specification that can be implemented by any language in any machine. The only requirement is that the binary form of the COM object must be the same as the dual binary form generated by the Microsoft VC compiler. In addition, COM can be used on other models, like Mac, SGI, and more, as long as they comply with the establishment and use of COM objects.

Finally, COM enhances the possibility of adding a large computer program (billions of lines) through its component level universal architecture. And of course, DirectX, OLE and ACRIVEX are COM based, so you need to understand COM.

A running COM program as a complete example of creating a COM object and several interfaces, I have created Demo5_1.cpp for you. This program implements a COM object called CCOM_OBJECT. This object consists of two interfaces, named IX and IY, respectively. This program is an implementation of a regular COM object. However, there are many advanced details such as creating DDL, dynamic loading, etc., but once all methods and iunknown classes are established, COM objects are fully implemented.

I want you to do the job is a careful reading code, modify the code to see how it works. Listing 5.1 includes all COM objects and a simple C / C main () driver full code. Listing 5.1 A complete COM object program // demo5_1.cpp - a Ultra Minimal Working COM EXAMPLE / / NOTE: NOTE FULLY COM Compliant

// incrudes ///

#include #include #include #include // Note that you must contain this header file. // It contains important constants you have to use in the COM program

// guids //

// Thase Were All generated with guidgen.exe

// {b9b8ape1-CE14-11D0-ae58-4444553540000} const IID {0xB9B8ACE1, 0xCE14, 0x11D0, {0xAE, 0x58, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0}};

// {B9B8ACE2-CE14-11D0-ae58-444553540000} const IID iID_IY = {0xB9B8ACE2, 0xCE14, 0x11d0, {0xAE, 0x58, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0}};

// {B9B8ACE3-CE14-11D0-ae58-444553540000} const IID IID_IZ = {0xB9B8ACE3, 0xCE14, 0x11D0, {0xAe, 0x58, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0}};

// Interfaces /

// define the ix interfaceinterface ix: iunknown {

Virtual void __stdcall fx (void) = 0;

}

// define the IY interfaceInterface IY: iUnknown {

Virtual void __stddcall fy (void) = 0;

}

// Classes and Components /

// define the com objectclass ccom_object: public ix, public {public:

CCOM_Object (): ref_count (0) {} ~ ccom_object () {}

Private:

Virtual HRESULT __STDCALL QUERYINTERFACE (Const IID & IID, VOID ** IFACE); Virtual Ulong __stddcall addref (); Virtual Ulong __stdcall release ();

Virtual void __stdcall fx (void) {cout << "Function FX Has Been Called." << Endl;} Virtual Void __stdcall fy (void) {cout << "Function Fy Has Been Called." << endl;} int REF_CONT ;

}

// Class methods //

HRESULT __stdcall CCOM_OBJECT :: QueryInterface (const IID & iid, void ** iface) {// this function basically casts the this pointer or the IUnknown // pointer into the interface requested, notice the comparison with // the GUIDs generated and defined in the Beginning of the program

// Requesting the IUNKNOWN BASE INTERFACEIF (IID == IID_IUNKNOWN) {cout << "Requesting iUnknown Interface" << Endl; * ifce = (ix *).

} // end if

// Maybe ix? if (iid == iid_ix) {cout << "Requesting ix interface" << Endl; * ifce = (ix *) THIS;

} // end ifelse // Maybe IYIF (IID == IID_IY) {cout << "Requesting IY Interface" << endl; * ifce = (ip *)

} // end ifelse {// Cant Find it! Cout << "Requesting Unknown Interface!" << Endl; * ifce = null; return (e_nointerface);} // end else

// if everything went well cast pointer to // iUnknown and call addref () ((iUnknown *) (* iFace)) -> addref ();

Return (S_OK);

} // End queryinterface

///

Ulong __stdcall ccom_object :: addRef () {// increments reason "<<" adding a reason "<< Endl; Return ( ref_count);

} // end addref

///

Ulong __stdcall ccom_object :: release () {// DECREMENTS Reference CountCout << "deleding a reason" << Endl; if (ref_count == 0) {delete this; return (0);} // end ifelse return (REF_COT) } // End Release

///

IUnknown * CoCreateInstance (void) {// this is a very basic implementation of CoCreateInstance () // it creates an instance of the COM object, in this case // I decided to start with a pointer to IX? IY would have // Done Just As Well

IUNKNOWN * COMM_OBJ = (ix *) New (ccom_Object);

COUT << "CREANG COMM Object" << Endl;

// Update Reference Countcomm_Obj-> addRef ();

Return (Comm_obj);

} // End CocreateInstance

//

Void main (void) {

// Create the main com objectiunknown * punknown = cocreateInstance ();

// Create Two Null Pointers the ix and IY interfacesix * pix = null; iY * piy = null;

// from the Original Com Object Query for Interface ixpunknown-> queryinterface (iiD_ix, (void **) & pix);

// Try some of the methods of ixpix-> fx ();

// Release the interfacepix-> release (); // now query for the IY interfacepunkNown-> queryinterface (iiD_iy, (void **) & piy);

// Try some of the methodspiy-> fy ();

// Release the interfacepiy-> release ();

// Release the com object itselfpunknown-> release ();

} // End main I have pre-compiled an executable program demo5_1.exe, but if you want to do some tests and want to compile DEMO5_1.cpp, be sure to remember to create a Win32 console application. Because DEMO is used in main () instead of WinMain ().

Collaboration with DirectX COM Objects Now, what is DirectX and how COM works. Let us further research on how they work together. As I said, DirectX is composed of many COM objects. When you load the runtime version of DirectX, the COM object is in the form of a DLL in your system. When you run a third-party DirectX game, the game will load one or more DLLs through the DirectX program, then the game application interface, the method corresponding to the interface is used to complete the work. This is a matter of time.

In the "compile time triangle", the situation is somewhat different (The Compile-Time Angle Is A Little Different). DirectX designers know that they face game developers, and they assume that most game developers have hated Windows programming methods. Oh, then they understand that it is best to make COM, some, and some, otherwise the game programmer will also hate DirectX. Thus, 90% of DirectX COM objects - relative to COM objects - packaged into very small function calls. So, you don't have to call CocreateInstance () and the like, for the initialization COM. DirectX is trying to hide the tedious detailed details when using COM objects so that you easily use the core features provided by DirectX. In summary, you must compile a DirectX program You must include a series of input libraries packaged for COM, so you can call DirectX, use these packaged functions, create a COM object. In most cases, below is the library you need: ddraw.libdsound.libdinput.libdInput8.libdSetup.libdPlayx.libd3dim.libd3drm.lib but remember that these input libraries do not include a COM object itself. These are just a packaging library, which just makes the call to the DirectX DLL, and the DirectX DLL really contains the COM object. Finally, when you call the DirectX COM object, the result of the call is often a pointer for an interface. The pointer points to the thing that is really doing things. Just like demo5_1.cpp, once you get the pointer of the interface, you can call the function at will, or use C terminology: method call. However, if you are a C programmer, if you don't know the function pointer, you can browse the next section. If you are a C programmer, if you like, you can skip your next section.

COM and function pointer Once you have created a COM object and get an interface pointer, you really get a VTABLE (virtual function table) pointer. Take a look at Figure 5.7. The application of virtual functions allows you to write function calls that can only determine which function calls only when "Run". This is the key to COM and virtual functions. In essence, C is rooted here. But you can also use the function pointer to implement the same function in C. Figure 5.7. Virtualistic Table Structure Function Pointer is a pointer for calling a function. Unlike a function that is hard-tied to some code, as long as the prototype of the function pointer is the same as the function you point to, you can move the function pointer. For example, if you want to write a drawing driver that draws a pixel to the screen. But then assume that you have to support many different graphics cards, and these graphics card works are different. As shown in Figure 5.8. Figure 5.8. Software designs that need to support different graphics cards You want to call these different graphics cards in the same way, but when inserting different graphics cards, the code inside the mapping function is different. Below is a typical C programmer's solution. Int setpixel (int X, int y, int color, int Card) {// What video (card) {copy ati: {/ * hardware specify code * /} Break; Case Voodoo: {/ * Hardware specific code * /} Break; Case Siii: {/ * Hardware specificic code * /} Break;... Default: {/ * standard vga code * /} Break;} // end switch

// Return SuccessReturn (1);

} // end setpixel

Have you seen the problem? First of all, that Switch statement is too horrible, it runs slow, the code is long, easy to mistake, and you will also modify the function when adding another newly supported graphics card. A better solution than strict c is to use a function pointer like it:

// Function Pointer Declaration, Weird Huh? Int (INT X, INT Y, INT Color); // Now Here's All Our Set Pixel Functions

Int setpixel_ati (int x, int y, int color) {// code for ati

} // end setpixel_ati

///

Int setpixel_voodoo (int X, int y, int color) {// code for voodoo

} // end setpixel_voodoo

///

Int setpixel_siii (int X, int y, int color) {// code for SIII

} // end setpixel_siii now, you are ready to eat. When the system starts, it checks which graphics card installed, and then set the general function pointer once and only once, make it point to the correct graphics function. For example, you want setpixel () to point to the ATI version of the function, you can encode: // Assigning a function Pointersetpixel = setpixel_ati; isn't it simple? Figure 5.9 Graphical display has all this. Figure 5.9. Use the function pointer to call different code blocks Note: From some extent, setpixel () is the alias of setpixel_ati (). This is the key to the function pointer. Now you call setpixel () in the usual call mode, but not call empty setpixel (), truly call setpixel_ati (): // this real color, setpixel_ati (10, 20, 4); setpixel (10, 20, 4); the focus is your encoding will always be the same. Just for different values ​​you assign a function pointer, the function pointer will represent different functions, do different things. All virtual functions are used to function pointers and combined with the programming language, as you have done.

Based on this idea, we will see how you complete your universal graphics driver design. Everything you have to do is testing which graphics card installed in the end, then set it once to point SetPixel () points to the appropriate setpixel * () function. Come. Take a look at the following code: int setCard (int Card) {// Assign THE FUNCTION POINTER BASED On The Cardswitch (CARD) {CASE ATI: {setPixel = setpixel_ati;

} Break;

Case voodoo: {setpixel = setpixel_voodoo;

Case Siii: {setpixel = setpixel_siii;} Break;

DEFAULT: BREAK;

} // End Switch

} // End setCard starts with your code, you call a setup function, such as: setcard (card); after you are very familiar. This is how to use the function pointer and virtual function in C . Let's take a look at how these technologies are used for DirectX.

Create and use the DirectX interface at this moment, I think you already know: COM is the collection of interfaces, and the interface is a simple function pointer (exactly vtable). Thus, when applying a DirectX COM object, everything you have to do is to create it, get an interface pointer, then call the function with the appropriate syntax. For example, I use the primary DirectDraw interface to demonstrate: First, you need three things to use DirectDraw to do test. • DirectDraw runtime COM objects and DDL must be loaded and registered. This is a DirectX installer. · You must include DDRAW.LIB input library in your Win32 program so that you can link to the function you call (Translator Note: This initiator often forgets, take VC6.0 as an example, the method is in the project -> setting -> Last Type of the "Object / Book Template" domain in the LINK page, the full name of the required input library, including the extension). · You must include DDRAW.H in your program so that the compiler can recognize the header file information, prototype declaration, and data types of DirectDraw. After you know these, the following is the data type of the DirectDraw 1.0 interface pointer: lpdirectdraw lpdd = null; and DirectDraw4.0 interface pointer data type: lpdirectdraw7 lpdd = null; and DirectDraw7.0: lpdirectdraw7 lpdd = null; but no 8.0 .

Create an interface pointer to create a DirectDraw COM object and get a DirectDraw object (DirectDraw object represents a graphics card), everything you have to do is DirectDrawCreate (): DirectDrawCreate (null, & lpdd, null); this will return Basic DirectDraw 1.0 interface. In Chapter 6, "First Touch: DirectDraw" I will discuss details about the participation. But now, just know, this call creates a DirectDraw object and assigns the interface pointer to LPDD.

Now, you are ready to do some calls for DirectDraw. Temporarily stay! You still don't know which functions or methods can be used, huh, this is the purpose of your book. As an example, the following code tells you how to set up a 640 × 480,256 color deep video mode:

LPDD-> SetvideOMode (640, 480, 256);

What else do you still say in addition to simple? The only additional job is "->" operation on the DirectDRAW interface pointer LPDD. Of course, what truly happens is the virtual function table of the interface, but here can't see this.

In essence, any call to DirectX is below the form:

Interface_pointer-> method_name (parameter list);

Of course, by using queryinterface (), you can jump from the initial DirectDRAW interface to any interface you want to use (such as DirectX3D). Even because there are multiple DirectX versions, and Microsoft stops writing a function of any latest interface, so sometimes you have to use queryinterface () to manually get the latest version of DirectX interface. Let us study this research.

The interface query DirectX is a strange place that all version numbers are not synchronized. This is really a problem, and it is definitely a source of confusion. Below is the reason why things: When the first DirectX version is released, the interface of DirectDraw is named: iDirectdraw and then DirectDRAW is updated to 2.0 when DirectX2.0 is released. So we have: iDirectdrawidirectdraw2 now, when DirectX6.0 is released, we see: iDirectdrawidirectdraw2idirectDraw4idirectdraw7 has arrived to DirectX8.0, no longer support DirectDraw. So the latest version of the DirectDraw interface you have is just iDirectdraw7. do you understand? Wait! No interface 3 and interface 5? I don't know, but this is really a problem. But the key is, even if you use DirectX8.0, this does not mean that the interface is also updated to 8.0. Further, the version number of the DirectX version number and the interfaces and the version numbers of each interface can be completely different. Directx6.0's DirectDraw interface version to iDirectDraw4, but the DirectSound interface is only 1.0, then call IDirectSound. Look at this chaotic. The above description is to tell you that when you use a DirectX interface, you should make sure that the interface you use is the latest version. If you are not sure, use a 1.0 version of the pointer and then create a function to get the latest interface version.

To explain what I just said, the following is an example: DirectDrawCreate () returns a 1.0 version of the interface pointer, but DirectDraw has reached IDirectDraw7, then how can you use new features? There are two ways: using a low-level COM function or use queryinterfaced (). Let us use the latter. The whole process is approximately as follows: First, you DirectDrawCreate () to create a DirectDraw COM interface, which returns an annoying iDirectDRAW interface pointer. You then use this pointer to call queryinterface () and get the iDirectdraw7 pointer through the interface ID (or GUID). Here is an example: lpdirectdraw lpdd; // version 1.0lpdirectdraw7 LPDD7; // Version 7.0

// Create Version 1.0 DirectDraw Object InterfaceDirectDrawCreate (NULL, & LPDD, NULL);

// Now Look in ddraw.h header, Find IDirectdraw7 interface // ID and use it to query for the interfacelpdd-> queryinterface (IID_IDIRECTDRAW7, & LPDD7);

At this moment, you have two interface pointers. But you don't need to point to the pointer to iDirectDraw. So you should release the pointer. // Release, Decrement Reference Countlpdd-> release ();

// set to null to be safelpdd = NULL;

Do you remember? When you run out, you should release the interface. Therefore, when your program ends you, you should also release the IDirectdraw7 interface, as follows: // Release, Decrement Reference Countlpdd7-> Release (); // set to null to be safelpddd7 = null;

OK, now you know how to get another interface pointer from an interface. By cumbersome, we have seen a hope in DirectX7.0. Microsoft adds a new function DirectDrawCreateex (), which returns directly to the IDirectDraw7 interface. Magical? But they also shot this function in DirectX8.0. But who cares? Anyway, we can still use this function: HRESULT WINAPI DirectDrawCreateEx (GUID FAR * lpGUID, // the GUID of the driver, NULL for active display LPVOID * lplpDD, // receiver of the interface REFIID iid, // the interface ID of the interface You are Requesting iUnknown far * punkouter // advanced COM, NULL); this new function allows you to send a IID to indicate the DirectDraw version you want to request, and then the function will create a COM object for you. We only need to call the function:

LPDIRECTDRAW7 LPDD; // Version 7.0

// Create Version 7.0 DirectDraw Object InterfaceDirectDrawCreateex (NULL, (Void **) & lpdd, iid_idirectdraw7, null;

Basically, the call to DirectDrawCreateex directly creates a desired interface. So you don't have to use DirectDraw1.0 as an intermediary. Ok, this is all knowledge about using DirectX and COM. Of course, you haven't seen hundreds of functions and interfaces with DirectX components. But later you will see.

Current CoM's future, many technologies similar to COM have been released, such as Corba (Common Object Request Broker Architecture). However, because you only care about Windows games, other technologies are not very important. The latest version of COM is COM , which is more powerful, rule, and well-thoughtful implementation details. COM makes it easier to develop distributed software components. It is true that COM is more complicated than COM, but hey, this is life. In addition to COM and COM , there is a complete Internet / intranet version of COM called DCOM (distributed COM). Worship DCOM, COM objects do not need to be provided on your machine, they can be provided by other machines on the network. Cool? Imagine your program as a client under a powerful DCOM server. According to me, it is really an incredible technology.

转载请注明原文地址:https://www.9cbs.com/read-40220.html

New Post(0)