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.
Users of Visual Studio 2005 should check the technical note .NET requirements to make sure that your development and runtime environments are properly configured.
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.
There are three .NET integration samples in the toolkit:
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:
/clris applied to C++ source files of your project.
xlpclrconvert.his included in your main cpp source file, and the namespace
ple::clris included by default.
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.
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++:
Do not use a pointer to a managed object, such as
System::Object* obj. Instead, you should use a handle,
System::String^ str = number.ToString();
You can use the
-> operator to access
the properties and methods of the object pointed to by the handle:
System::String^ str = "Quick brown fox"; int len = str->Length;
When you create an instance of a managed class, you should use gcnew instead of new.
System::Object^ obj = gcnew System::Object();
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.
// 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.:
double d = a[1, 2]; b = "Hello";
Generally, you should use
safe_cast<T, S>(S s)
to cast a managed object
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.
_Application^ theApp; _Worksheet^ ws = safe_cast<_Worksheet^>(theApp->ActiveSheet);