Using Exceptions Across Languages
One of the great things about managed exceptions in C++ is that they work across languages, so now you can, for example, throw an exception in C++ and catch it in a Visual Basic application. No longer are exceptions simply a C++ feature, and this ability to harmonize error handling across code written in different languages makes mixed-language programming much easier than it has been in the past. In the final example in this module, you will create a C++ class in a dynamic link library (DLL) and then use the class in a Visual Basic application.
You will need to have Visual Basic .NET installed to complete the second part of this example.
1. Start Visual C++/Studio .NET, and create a new Visual C++ project. This time, choose a Class Library project, which is used when you want to create a DLL rather than an EXE. Named the project MyClass. You can name it what you like, but make a note of the name.
|
You’ll find that you’ve created a project that defines a namespace named MyClass, containing a single class named Class1.
It’s this class that you’ll edit, adding a method that can be called from a Visual Basic client. The project will contain a number of files, among them MyClass.h and MyClass.cpp which are used to hold the definition and implementation of the Class1 class.
2. Open MyClass.h, and add the Test function so that it looks like the following code:
// MyClass.h
#pragma once
using namespace System;
namespace MyClass {
public ref class Class1
{
// TODO: Add your methods for this class here.
public:
void Test(int n)
{
if (n < 0)
throw gcnew ArgumentException(L"Argument must be positive");
}
};
}
The Test method should look familiar by now: it simply checks its argument and throws an exception if it’s less than 0.
3. Build the project. You’ll end up with a DLL being created in the project’s debug directory.
4. Close the project, and create a new Visual Basic Console Application project, which we named Tester. The following example uses Visual Basic .NET 2005 (Visual Studio 2005 Standard Edition).
5. Before you can access the C++ DLL you just created, you have to add a reference to it to the project. To do so, open Solution Explorer, select My Project sub folder, right clicks and select Open (or just double click My Project link).
6. On the left pane menu, click the References link.
7. Click the Add… button and select Reference…
8. Choose Add Reference from the drop-down menu, and when the dialog box appears, click Browse tab and search for the DLL you built in the previous step. Make sure it’s added to the References pane, and then click OK.
At the bottom, in the Imported namespaces, you will see MyClass.
9. Now you can add the code to the project. Edit the Main() function (Module1.vb) so that it looks like the following code:
' Application to demonstrate cross-language exception handling
Imports [MyClass]
Module Module1
Sub Main()
Dim obj As New Class1()
Try
obj.Test(-1)
Catch e As ArgumentException
Console.WriteLine("Exception: " & e.Message)
End Try
Console.WriteLine("All work done")
End Sub
End Module
The first line imports the MyClass namespace into the program. This line does the same job as using namespace does in C++, so you don’t have to fully qualify the name Class1 when it appears. The first line in the Main function creates a new Class1 object, and it’s equivalent to creating an object in C++ using new. The call to the Test function is enclosed in a try and catch construct, and you can see the similarity between the way exceptions are handled in Visual Basic and C++. The main difference is that in Visual Basic, the catch blocks are inside the try block.
10. Build the code, and execute it. Passing -1 through as the argument will trigger the exception, and you should see the message printed out in the catch block.
Quick Reference
To | Do this |
Generate an exception. | Use the throw keyword, using a pointer to a managed type as the argument. For example:
throw new SomeException();
|
Catch an exception. | Use the try and catch construct, surrounding the code that might fail with a try block, followed by one or more catch blocks. For example:
try { // code that might fail } catch(SomeException* pce) { // handle the exception }
|
Catch more than one exception. | Chain catch blocks together. For example:
catch(SomeException* pce) { // handle the exception } catch(SomeOtherException* pce) { // handle the exception }
|
Catch a family of exceptions. | Use the base class of the exceptions you want to catch in the catch block; for example, ArithmeticException will catch DivideByZeroException and several others. |
Catch every exception. | Use a catch block that takes Exception^ as a parameter, which will catch every type that is derived from Exception. |
Handle exceptions at more than one point in a program. | Use throw to re-throw exceptions from one catch block to another. |
Table 4 |