Because the MathLibrary project created a static library, a .LIB file, you can use it from other applications that are outside the AllInOne solution. Typically you deploy a library like this as the .LIB file and the associated header file (or files). In order to create the sample applications in this section, you should copy the .LIB and .H files from the AllInOne folder to another location, to more closely resemble the circumstances under which you would use a real class library. Creating a Release Version of the LibraryThe instructions so far in this chapter created a debug version (also called a Debug build) of the library, and a debug version of the test harness to go with it. For distribution to other developers, it's better to create a release version. This has many advantages, including
These are the most significant differences between the default Debug build and the default Release build. Once you are experienced working with different kinds of builds, you can use the Properties page for the project to tweak your settings. To build a release version of MathLibrary.lib, follow these steps:
Build and run the application to be sure you made all your changes correctly. Calling the Library from an Unmanaged C++ ApplicationTo call the library methods from another application, start by creating an application. The sample in this section is an MFC application just to show that class libraries aren't restricted to console applications. Here's how to create the application and start using methods from the library:
At this point, the dialog box has been created, and all the required variables and methods have been added to the associated class. In order to actually code the button handler, the compiler and linker must be told about the library. Copy the header file, Arithmetic.h, and the release version of the library, MathLibrary.lib, to another folder on your computer. In the instructions that follow, that folder is assumed to be C:\MathLibrary . Just like the Harness project that tested the library, the UseLibrary project has settings that can be changed to ensure the compiler and linker can find the class definition and the executable code. Add the folder C:\MathLibrary to the Additional Include Directories property by right-clicking UseLibrary in Solution Explorer and expanding C/C++ and then selecting General and entering the path. Then expand the Linker folder and select input, and enter the full path to the .LIB file. When the library was created, it included a reference to the C runtime library (CRT). Microsoft ships many different versions of the CRT with the compiler. The default settings when creating a static library include the single-threaded version of the CRT. This is also the default for console applications, so both Harness and MathLibrary used the same version of the CRT. However the MFC dialog-based application created in this section uses the multi-threaded debug DLL version of the CRT. As a result, all the functions in the CRT are linked in twiceonce from the single-threaded version of the CRT and once from the multi-threaded debug version. This causes linker errors such as this: LIBC.lib(malloc.obj) : error LNK2005: _malloc already defined in msvcrtd.lib(MSVCR71D.dll) LIBC.lib(crt0dat.obj) : error LNK2005: _exit already defined in msvcrtd.lib(MSVCR71D.dll) The project will not build at this point. There are several approaches to solving this problem, some better than others:
To instruct the linker to ignore the single-threaded version of the CRT, bring up the properties for the UseLibrary project. Expand the Linker folder and select Input. Click next to Ignore Specific Library and type libc.lib this is the name of the single-threaded release version of the CRT. Now the project builds successfullyand you don't have to change the library. The file UseLibraryDlg.cpp is where the button click handler has been added. At the top of this file, after the include statements already present, add an include statement: #include "arithmetic.h"
The handler for the button click creates an instance of the Arithmetic class and uses it to add the numbers that were entered in the edit controls. Then it converts the answer to a string and uses that as the new caption for the static text control. The code looks like this: void CUseLibraryDlg::OnBnClickedButton1() { UpdateData(true); Arithmetic a; double ans = a.Add(num1,num2); CString answerstring; answerstring.Format("%g",ans); answer.SetWindowText(answerstring); } The call to UpdateData() copies the entries from the actual controls on the dialog box to the member variables you mapped to them with the Add Variable wizard. Now you have seen how to use a simple class library from an unmanaged C++ console application and an unmanaged C++ MFC dialog-based application. There is no difference in technique when the library is in the same solution as the calling code or in a different solution: You still need to inform the compiler and the linker of the location of the library's header and .LIB files. When you are using the library from an application that uses the multi-threaded version of the CRT, you need to instruct the linker not to bring the single-threaded version in with the library. Calling the Library from a Managed C++ ApplicationUsing the library from another unmanaged C++ application was straightforward. Using it from a managed C++ application is also straightforward, even though it combines managed and unmanaged code in one application. Start by creating a managed C++ console application called ManagedUseLibrary . Update the Additional Include Directories, Additional Dependencies, and Ignore Specific Libraries properties just as for the MFC dialog-based application. Here is the code for the main function: #include "stdafx.h" #using <mscorlib.dll> using namespace System; #include "arithmetic.h" int _tmain() { Arithmetic a; Console::Write(S" 1.2 + 3.2 = "); Console::WriteLine(__box(a.Add(1.2, 3.2))); Console::Write(S" 2.1 * 3 = "); Console::WriteLine(__box(a.Multiply(2.1, 3))); Console::ReadLine(); return 0; } It's as simple as that to use an unmanaged class library from a managed application. The C++ team at Microsoft call this "It Just Works"and it does! You'll also see It Just Works referred to as IJW.
Calling the Library from Other Managed LanguagesIf you've been reading about the Common Language Runtime and how all the managed languages use the same class libraries and share the same capabilities, you might well assume that the library created in this chapter can be used from Visual Basic .NET and Visual C# as easily as from managed C++. However, that's not the case. All the languages share the same libraries, and produce code that is easily compatible. Code written in managed C++ can be used in a Visual Basic .NET application without any difficulty at all. Managed C++ code can use code written in C# as simply as though it were written in C++. Butand this is a huge advantage of C++the other languages cannot access unmanaged code using It Just Works. There are several techniques for calling unmanaged C++ code from Visual Basic .NET or C#:
|