Managed C++ and .NET Development: Visual Studio .NET 2003 Edition
Creating a Managed C++ Application
I guess I could have made the example easy and just put all the application code in Cards.cpp, but I decided to add a little real-world programming and separate the library from the application. This being the case, you will start by creating another project to place the application in. You have two options:
-
Create the project as its own solution.
-
Include the project in the Chapter06 solution you already created.
It might make more sense to separate the application if the library you just created is going to be shared by multiple applications. But, in this case, the library is going to be used only with this application, so you will add the project to the Chapter06 solution.
You have already seen how to create a project. The only difference between a library and an application project is that you select the Console Application (.NET) icon in the Templates window, as shown in Figure 6-27, and the name of the project is DeckPlayer.
Now all you have to do is replace the autogenerated code with the code in Listing 6-6 in the autogenerated DeckPlayer.cpp file (you have already seen this in Chapter 3). Then you are ready to test your application.
Listing 6-6: Complete DeckPlayer.cpp File
#include "stdafx.h" using namespace System; using namespace Cards; Int32 main(void) { Deck &deck = *new Deck; deck.Shuffle(); Card *card; Int32 i = 0; while ((card = deck.Deal()) != 0) { if (i < 6) { Console::Write(S"{0}\t", card->ToString()); i++; } else { Console::WriteLine(S"{0}\n", card->ToString()); i = 0; } } Console::WriteLine(S"\n"); return 0; }
If you recall, in Chapter 3, you used the line #using <Cards.dll> to reference the class library assembly. This command makes the assembly available to the application and provides declarations so that no header file is needed for the library. You may have noticed now that #using <Cards. dll> is no longer at the top of the source. In fact, you do not see any #using statements. The reason is that Visual Studio .NET provides a folder called References that contains all referenced assemblies so you no longer need to include the statement in the source. (You can still include it if you want, but it is not needed.)
Go ahead and compile DeckPlayer exactly as you compiled the Cards assembly. The easiest way to do so is to press Ctrl-Shift-B. Once the compiler is finished, you should have another "build succeeded" message in the Output window.
Before you run the new program, you have to let Visual Studio .NET know which project contains the starting point for the application. In other words, you have to let Visual Studio .NET know which project contains the main() function. To do this, right-click the DeckPlayer project folder in Solution Explorer and then select the Set as Startup Project menu item. Now run the new program by selecting Debug ➣ Start Without Debugging from the main menu or by pressing Ctrl-F5. If everything goes as it should, you see output similar to that shown in Figure 6-28. Of course, the order of the cards will be completely different; otherwise, it wouldn't be much of a shuffle routine.
Let's see what you built. If you've worked with Visual Studio in the past, you would expect that DeckPlayer.exe would be in the Debug directory within the DeckPlayer project directory that you created when you first built the project (unless you're in the release configuration, in which case it should be in the Release directory). Look all you want, it isn't there. Visual Studio .NET placed it in the Debug directory off of the Solution directory. This is one of the bonuses of creating a solution and then placing projects within it. Why is it a bonus? It saves you from having to worry about assembly referencing because all assemblies in the solution are placed in the same directory. Remember, all assemblies for an application must be in the same directory or in the GAC.
Okay, let's simulate the application-development scenario where the class library assemblies and the executable assembly are in different solutions. (This scenario will probably be more the norm when you start developing your own applications.)
So how do you get DeckPlayer.exe back in the Debug directory where you expect it to be? The reason that the program is in the solution's Debug directory can be found in the DeckPlayer Property Pages (see Figure 6-29) and the Cards Property Pages. You can find these pages by right-clicking the DeckPlayer or Cards project folder and selecting the Properties menu item. Do you notice that the Configuration Properties ➣ General ➣ Output Directory text box contains the macro $(SolutionDir)$(ConfigurationName)? Well, that's the culprit. This macro tells the compiler to place DeckPlayer.exe and Cards.dll in the solution's Debug directory.
To place the DeckPlayer and Cards project assemblies back into their own Debug directories, you need to do the following for both projects:
-
Open the appropriate Property Pages by selecting Properties from the menu item presented after you right-click the Project folder within Solution Explorer.
-
Change the Configuration drop-down box to All Configurations.
-
Delete the $(SolutionDir) macro from the Configuration Properties ➣ General ➣ Output Directory text box.
Once you have done this for both projects, you have in effect created two projects that reside in the same directory structure.
Now let's build DeckPlayer. Oops... I got the error shown in Figure 6-30.
Referencing an Assembly for Compilation
What has happened here? The program worked when it was built in the previous solution. The difference is that, in the previous solution, all the assemblies compile to the same directory, thus allowing the compiler to find Cards.dll. Now, on the other hand, Cards.dll is in a different directory from DeckPlayer.exe and thus not readily available for referencing.
In the first release of Visual Studio .NET, the solution for Managed C++ to this problem was to manually specify the location of Cards.dll to Visual Studio .NET and then copy Cards.dll to the same directory as DeckPlayer.exe so that it could be referenced. Fortunately, now the process is a lot easier because it is handled by a Visual Studio .NET menu option, as follows:
-
Highlight the DeckPlayer project within Solution Explorer.
-
Select Project ➣ Add Reference from the main menu. The Add Reference dialog box appears, as shown in Figure 6-31.
Figure 6-31: The Add Reference dialog box
Alternatively, you could follow these steps:
-
Right-click the Reference folder within the DeckPlayer project.
-
Select the Add References menu item. The Add Reference dialog box appears, as shown in Figure 6-31.
-
Select the Projects tab.
-
Select the Cards project. If there is more than one assembly you need to reference, select multiple projects.
-
Click the Select button.
-
Click the OK button.
What this process does in effect is automatically perform the manual steps that I described previously. So, if you look in the Debug directory of the DeckPlayer project, you will find Cards.dll. An added bonus is that if you make any changes to the Cards project, the next time you compile the DeckPlayer project, the new Cards.dll will be copied over, thus keeping DeckPlayer in sync with all its referenced assemblies.
Now when you run DeckPlayer.exe, it works exactly as it did when it was within the solution, except it is running from DeckPlayer's Debug directory and not the solution's Debug directory.
Категории