A common software requirement is for code written in one computer language to be used by software developed in a different computer language. For instance, it may be necessary to access C functions from a .NET or Java application. In this article, I show how existing C software can be wrapped in C++ and thus made easily accessible from .NET languages such as C# and VB.NET. Although I use the NAG C library from the Numerical Algorithms Group (http://www.nag.co.uk/) as an example, the method is general and can be applied to other C software. In particular, I illustrate the technique by considering four NAG C library numeric routines, which have applications in computational finance:

- NAG function
**s15abc**, the cumulative normal distribution that is used in analytic option pricing formulae, such as the Black-Scholes equation [1]. - NAG function
**f02aac**, the eigenvalue computation. This has applications in multifactor models, including interest-rate models and time series [2], [3]. - NAG function
**d01ajc**, numerical integration, which has applications in risk analysis [4]. - NAG function
**e04dgc**, numerical optimization. This can be used to compute optimal portfolios [5].

### COM, .NET Assemblies, and Managed C++

Microsoft COM already enables the creation of numeric components that can be used by the complete range of Windows programming languages. In fact, COM objects can be used within .NET. However, from a programmer's point of view, wrapping C code in COM C++ classes has the disadvantage that there is visible Microsoft COM baggage that needs to be carried around. This has the effect of obscuring the code and also making it difficult to implement the C++ classes on UNIX platforms. Another limitation is that the classes contained within a COM object cannot be used to create other derived classes.

.NET assemblies have improved this situation. In a nutshell, the classes in an assembly can be coded in any .NET language, then used by any other .NET language. Thus, it is possible to create assemblies in managed C++ that provide class wrappers for C routines, then use these from C# and VB.NET software [6].

Listing 1 shows the ANSI function prototypes of four NAG C functions. Listing 2 is the managed C++ code used to create an assembly that wraps the C functions. I call this assembly "naglib," and it defines the namespace **NAGLIB** and the managed class **NAG_FUNCTIONS,** which provides functions to access native C routines contained within the DLL "nagc." Listing 2 is meant for illustrative purposes and not intended to be a statement of good programming practice. However, I have included some useful features, such as flagging errors and setting default parameter values via the constructor **NAG_FUNCTIONS()**.

As you can see, the code is almost standard C++ and (in contrast to the equivalent COM approach) could easily be ported to UNIX platforms. I now examine each nonstandard C++ (that is, Microsoft-specific) feature.

The NAG C library routines used are contained in a DLL called "nagc." Here, each function is imported into the C++ project by name. For instance:

[DllImport(</b>"<b>nagc</b>"<b>)] extern </b>"<b>C</b>"<b> Double s15abc(Double x);

is used to import the function **s15abc**, which computes the cumulative normal distribution.

The directive **gc** indicates that the code is managed and memory is allocated on the garbage collected (GC) heap; unmanaged code is indicated by **nogc**.

In Listing 2, the .NET data types **Double** and **Int32** have been used so that the assembly can be accessed by both C# and VB.NET code. All managed .NET code written in VB.NET, C#, and C++ is compiled to the same intermediate language (IL) code. To permit interoperability within .NET, there is a common type system (CTS) that standardizes the basic data types across all languages. Table 1 provides a summary of the .NET data types corresponding to the C++ types **double** and **long**.

In the case of numerical integration and optimization, user-defined functions (or call-back functions) need to be passed as parameters to the NAG C library routine. This is done in .NET by declaring a delegate with the same signature (that is, return type and parameter types) as the callback function. For example:

public __delegate double INTEGRAND_FUN_TYPE(Double x);

declares the delegate **INTEGRAND_FUN_TYPE** with a signature corresponding to functions that return a **Double** and have a single **Double** parameter passed by value. This delegate is used by the numerical integration routine **d01ajc** for defining the integrand. The declaration of a delegate is similar to the declaration of a function prototype with the additional words **public** (or **private**) and **delegate**. Also, the declaration and use of delegates in Listing 2 has similarities with the declaration and use of function pointers in Listing 1.

A more complicated delegate example is:

public __delegate void OBJ_FUN_TYPE (Int32 n, double *x, double * objf, double *g, Int32 comm);

which declares the delegate **OBJ_FUN_TYPE.** This is done with a signature that applies to subroutines (that is, functions that return **void**) with parameters of type **Int32** and** double ***. As you can see, I had to use **double * **instead of the more general **Double ***. This delegate is used by the numerical optimization routine **e04dgc** for specifying the objective function to be minimized.

### Accessing the Naglib Assembly from C#

The C# code in Listing 3 (and project screen in Figure 1) illustrate how the assembly naglib can be accessed from a C# console project created using Visual Studio .NET. You can see that the C# code defines the classes **DCLASS** and **RUNIT**. **DCLASS** is derived from the class **NAG_FUNCTIONS** and supplies definitions for the callback functions used by the member functions **OPTIMIZE** and **QUADRATURE**.

The class **RUNIT** only contains the member function **Main**. This function is run by the example console application, and all the computations are performed by a single numeric object (**tt**) of type **DCLASS**.

The assembly containing the namespace **NAGLIB** is accessed with the statement using **NAGLIB**, which occurs on the third line of Listing 3. (See Listing 4 for the output from Listing 3.) I use **Math.PI **to return the value of , **Math.Sin(x) **to** **compute** sin(x)**, and **Math.Exp(x)** to evaluate **exp(x)**. These functions are members of the class **Math**, which is contained in the namespace **System**.

This directive is necessary because C# does not really support pointers. The keyword **unsafe** lets you use pointers and thus easily pass scalars and arrays by reference to the managed C++ class **NAG_FUNCTIONS** contained in the namespace **NAGLIB**.

The statement **DCLASS tt = new DCLASS()** creates a numeric object **tt** with the type of the derived class **DCLASS**. Since **DCLASS** was derived from **NAG_FUNCTIONS**, it allows access not only to the public member functions **objfun** and **the_integrand_c**, but also the public member functions of **NAG_FUNCTIONS**: **CUM_NORM**, **OPTIMIZE**, **QUADRATURE**, and **REAL**_**SYMM_EIGEN**. This means that I can compute the cumulative normal distribution and perform eigenvalue computations by using statements of the form:

the_answer = tt.CUM_NORM(x); flag = 0; // first row a[0,0] = 0.5; a[0,1] = 0.0; ... // fourth row a[3,0] = -2.6; a[3,1] = -0.7; a[3,2] = 0.0; a[3,3] = 0.5; tt.REAL_SYMM_EIGEN(n, ref a[0,0], tda, ref r[0], ref flag);

Note that the keyword **ref** is used to pass the address of **a[0,0]**, **r[0]**, and **flag** to the member function **REAL_SYMM_EIGEN**.

### Using Numeric Objects with Member Functions Requiring Delegates

We will now consider how to call the numerical integration function **QUADRATURE**. This is achieved using the following C# statement:

INTEGRAND_FUN_TYPE myfun_c = new INTEGRAND_FUN_TYPE (tt.the_integrand_c);

to declare (and also define) the delegate** myfun_c**, of type **INTEGRAND_FUN_TYPE**, which corresponds to the user-defined function **the_integrand_c** contained in the derived class **DCLASS**. The next step is to pass the appropriate parameters to the function **tt.QUADRATURE**. For example:

a1 = 0.0; b1 = Math.PI*2.0; flag = 0; the_answer = 0.0; tt.QUADRATURE(a1, b1, ref the_answer, ref abserr, ref flag, myfun_c);

The method for calling the numerical optimization member function is similar. For instance, in the example code, we use:

OBJ_FUN_TYPE myobjfun = new OBJ_FUN_TYPE (tt.objfun); x2[0] = -1.0; x2[1] = 1.0; n2 = 2; flag = 0; tt.OPTIMIZE(n2, ref x2[0], ref g[0], ref objf, ref flag, myobjfun);

The initial parameter estimates and computed optimal values are contained in the array **x2**. The estimated gradient at the solution point is returned in the array **g**, and the parameter **objf** contains the value of the minimized objective function.

### Accessing the Naglib Assembly from VB.NET

The assembly naglib can be used from VB.NET in a similar manner to that described for C#; see Listing 5.

### Conclusion

A major benefit of the approach presented here over COM is that the managed C++ wrapper code can, with little effort, be used on UNIX platforms. In addition, unlike COM, you can create C# or VB.NET derived classes from the managed C++ (base) classes. As more software supports .NET (as, for example, Excel 2003 will), the future of object-oriented numerics in .NET looks promising.

### References

[1] Black, F. and M. Scholes. "The Pricing of Corporate Liabilities," *Journal of Political Economy*, 1973.

[2] Rebonato, R.* Interest-rate Option Models*, Second Edition, John Wiley, 1998.

[3] Levy, G.F. *Computational Finance, Numerical Methods for Pricing Financial Instruments,* Heinemann Press, 2003.

[4] Hull, J.C. *Options Futures and Other Derivatives*, Prentice Hall, 1997.

[5] Markowitz, H.M. "The General Mean-Variance Portfolio Selection Problem," *Phil. Trans. R. Soc. Lond.* 1994.

[6] Challa, S. and A. Laksberg. *Essential Guide to Managed Extensions for C++*, Apress, 2002.

**George Levy**, who holds a doctorate in mathematical physics from Oxford University, is a consulting software engineer and author of the upcoming book*Computational Finance: Numerical Methods for Pricing Financial Instruments.*He can be contacted at compukalc.com@ntlworld.com.