XLL+ Class Library (7.0)

Using .NET and the Common Language Runtime

.NET Integration

Starting with XLL+ 6.0.4, .NET integration is fully supported for XLL+ add-ins authored in Visual Studio 2005, Visual Studio 2008 and Visual Studio 2010.

Before you start

Users of Visual Studio 2005 should check the technical note .NET requirements to make sure that your development and runtime environments are properly configured.

Importing .NET Assemblies

XLL+ (6.2 and above) includes a set of tools to import a .NET assembly into an add-in. Point the tools at your assembly, and they will generate wrapper functions for you, with little or no assistance from you. See the topic Importing .NET Assemblies for full details.

If you want to write an add-in primarily in C++, but use some .NET code, then continue with this topic.

Samples

There are three .NET integration samples in the toolkit:

AppWizard - CLR option

If you want to use the Common Language Runtime in your add-in, you must select the CLR option in the AppWizard when you create your project.

The effects of setting this option are:

As a result, you are able to use CLR classes and methods from within your XLL. This includes the members of the standard .NET libraries, and any of your own .NET assemblies.

Calling .NET methods

Your code can call .NET methods, create .NET objects and do anything that any CLR-compliant langauge can do.

The notation for calling .NET from C++ is discussed in detail in the Visual Studio help. There are many new language features in C++/CLI, but only a few of them are used in this discussion. The following language features are important when using managed classes from C++:

Handles

Do not use a pointer to a managed object, such as System::Object* obj. Instead, you should use a handle, expressed as System::Object^ obj.

CopyC++
System::String^ str = number.ToString();

You can use the -> operator to access the properties and methods of the object pointed to by the handle:

CopyC++
System::String^ str = "Quick brown fox";
int len = str->Length;
gcnew

When you create an instance of a managed class, you should use gcnew instead of new.

CopyC++
System::Object^ obj = gcnew System::Object();
array<T, n>

Common Language Runtime arrays are represented using the array template. The second parameter is the rank of the array; if omitted, it is assumed to be 1 - i.e. a vector.

CopyC++
// Create a 2-dimensional array of numbers 
array<double, 2>^ a = gcnew array<double, 2>>(rows, columns);
// Create a vector of string handles 
array<System::String^>^ b = gcnew array<System::String^>(count);

Items within the array can be read or written using indexing, e.g.:

CopyC++
double d = a[1, 2];
b[3] = "Hello";
safe_cast<T, S>(S)

Generally, you should use safe_cast<T, S>(S s) to cast a managed object s of type S to type T. If the cast fails, an exception of type InvalidCastException will be thrown.

Many Excel object model properties return an untyped result, which needs to be cast to a useful type. Use safe_cast for this purpose.

CopyC++
_Application^ theApp;
_Worksheet^ ws = safe_cast<_Worksheet^>(theApp->ActiveSheet);

Next: Converting to and from .NET types >>