Sample Microsoft Visual Basic .NET projects illustrating how to call the NAG C Library Mark 25
The information here is applicable to the DLLs supplied with CLW3225DAL.
This web page contains links to several zip files, each containing a Microsoft Visual Basic .NET project showing how to call a NAG C Library function. These projects have been built and tested under Visual Studio 2010 and also tested with Visual Studio 2012 and Visual Studio 2013. They should run without modification under those platforms. To run these projects under later versions of Visual Studio, you may need to use the Visual Studio conversion wizard to convert the project. There are separate examples showing how to call the Library from Visual Basic 6 (VB6) and from Excel using Visual Basic for Applications (VBA).
- misc_functions.zip (includes examples for g02eec, s17dgc, e04cbc, x03aaw & x03aax, f04cec, f04cfc, x04nac & x04nbc, s15ddc and m01csc)
The file clvbdnet.vb contains the VB declaration of each user-callable NAG C Library function and all Enum and Structure (Type) declarations necessary for the parameters (mandatory and optional). This file can be imported into your VB project.
The header file is based on the stand-alone version of the NAG C Library DLL (CLW3225DA_nag.dll); to specify the version of the DLL which uses the MKL BLAS/LAPACK instead (CLW3225DA_mkl.dll), replace CLW3225DA_nag.dll by CLW3225DA_mkl.dll in the Function and Sub declarations.
Note that unlike VB6, VB.NET does not support "Option Base 1", so all arrays start at 0.
Remember also that to be able to use the NAG C Library DLL, its location will need to appear somewhere in your current path. If the DLL is in C:\Program Files\NAG\CL25\clw3225dal\bin (for example), then your PATH environment variable must contain this folder before starting Visual Basic. You will also need the folder containing the Intel run-time libraries on your path (unless these are already present). If you are using the MKL-based version of the NAG C Library (CLW3225DA_mkl.dll), then the folder containing the MKL DLLs should also be on your path, but should appear later in the path than the bin folder for the NAG C Library DLLs, e.g.
C:\Program Files\NAG\CL25\clw3225dal\bin; C:\Program Files\NAG\CL25\clw3225dal\rtl\bin; C:\Program Files\NAG\CL25\clw3225dal\mkl_ia32_11.2.1\bin; <rest of path>
In the NAG C Library function declarations, arrays are declared only with their type. In .NET all arrays are reference types, so an array variable contains a reference to the array and not the array itself. Therefore, a VB array variable can be simply passed by value to a NAG C Library function and VB.NET will pass the address of the array to the C code.
Declare Sub e04cbc Lib "CLW3225DA_nag.dll" ( _ ..., <[In](),Out()> ByVal x As Double(), ... ... Dim x(n - 1) As Double ... Call e04cbc(..., x, ...)
All arrays in the NAG C Library are declared as one-dimensional arrays. For consistency, the VB declarations of the NAG C Library functions also contain only one-dimensional arrays. It is, however, possible to use multidimensional arrays. In order to do this, the appropriate declaration needs to be changed.
'Changed from ' <[In](), Out()> ByVal b As Complex(), _ 'to ' <[In](), Out()> ByVal b As Complex(,), _ Declare Sub f04cfc Lib "CLW3225DA_nag.dll" ( _ ... <[In](), Out()> ByVal b As Complex(,), _ ... )
Please see the f04cfc example in the MiscFunctions project for an example of using a two-dimensional array.
In the VB.NET declarations of NAG C Library functions and subroutines, call-back function dummy arguments are declared as delegates.
Delegate Function d01sjc_f_DELEGATE( _ ByVal x As Double, _ ByRef comm As Nag_User _ ) As Double Declare Sub d01sjc Lib "CLW3225DA_nag.dll" ( _ ByVal f As d01sjc_f_DELEGATE, _ ...
The pointer to the actual function is passed using the VB AddressOf operator.
Call d01sjc(AddressOf fun1,...
In some cases, we might want to pass a null function pointer instead of a pointer to a call-back function. This can be done using Nothing.
' We are passing null pointer instead of providing pederv Call d02ejc(neq, AddressOf fcn, Nothing,...
Please see the d01sjc, d02ejc, e04dgc and e04nfc projects for examples of call-back functions.
Array Arguments to Call-back Functions
When array arguments are passed to a call-back function, VB.NET passes their address. Hence we have access to a pointer to the array. In the case of input array arguments, the appropriate amount of storage has to be copied to a VB array before it can be used. At the end of the function, output arrays must be copied back to the pointer.
In the examples, the Copy method of the Marshal class is used to do this copying. This method is overloaded to cater for different source and destination types, e.g.
Public Shared Sub Copy (source As IntPtr, destination As Double(), _ startIndex As Integer, length As Integer) Public Shared Sub Copy (source As Double(), startIndex As Integer, _ destination As IntPtr, length As Integer)
We need to import System.Runtime.InteropServices for this method.
Here is an example of how to use Marshal.Copy in a user-supplied function called funct.
Sub funct(ByVal n As Integer, ByVal ptr_x As IntPtr, _ ByRef obj As Double, ByRef comm As Nag_Comm) Dim x(n - 1) As Double 'Copy elements pointed to by ptr_x into local array x. Call Marshal.Copy(ptr_x, x, 0, n) ' The array x can now be used. ... ' If x is updated, copy it back to the pointer ptr_x Call Marshal.Copy(x, 0, ptr_x, n)
Examples of how to handle arrays in call-back functions can be found in d02ejc, e04dgc, e04nfc and in the e04cbce code within the MiscFunctions example.
C Library Typedefs and VB.NET Structures
Assigning pointers in VB.NET Structures
Pointers in the VB.NET structures defined for the NAG C Library are declared as IntPtr. In order to assign, for example, a VB Double array to such a pointer, code such as the following may be used.
<StructLayout(LayoutKind.Sequential)> Structure Nag_Spline ... Dim lamda As IntPtr ' Pointer to Double ... End Structure ... Dim lamda(ncap7 - 1) As Double Dim spline As New Nag_Spline ... ' Allocate some memory to spline.lamda spline.lamda = Marshal.AllocHGlobal(ncap7 * Len(lamda(0))) ' Then copy local lamda array to the allocated memory. Marshal.Copy(lamda, 0, spline.lamda, ncap7)
The Marshal.Copy overload used here is
Public Shared Sub Copy (source As Double(), startIndex As Integer, _ destination As IntPtr, length As Integer)
To access the array pointer stored in the VB structure we again use Marshal.Copy. The overload used is
Public Shared Sub Copy (source As IntPtr, destination As Double(), _ startIndex As Integer, length As Integer)
We need to import System.Runtime.InteropServices for this method.
In, for example, a user-supplied function such an array may be accessed by first copying it to a VB array. If the array is updated it must then be copied back. This is done in the same way as with a pointer to an array passed to a call-back function.
Dim mycomm(3) As Double '4 elements ' Copy from pointer to local array Call Marshal.Copy(comm.p, mycomm, 0, 4) ... ' Copy back from local array to pointer Call Marshal.Copy(mycomm, 0, comm.p, 4)
Assigning pointers in VB.NET structures is illustrated in the e02bac and d02ejc example projects.
Assigning function pointers in VB.NET Structures
The function pointer is declared as a delegate passed by value. For example:
Delegate Sub NAG_E04_PRINTFUN_DELEGATE ( _ ByRef p1 As Nag_Search_State, _ ByRef p2 As Nag_Comm _ ) ... Sub set_print_fun(ByVal ptr_fun As NAG_E04_PRINTFUN_DELEGATE, _ ByRef options As Nag_E04_Opt) options.print_fun = ptr_fun End Sub
The call to this function uses the AddressOf operator to pass the address of the user-defined function, called monit in this example.
Call set_print_fun(AddressOf monit, options)
Assigning function pointers in VB.NET Structures is illustrated in the e04dgc example project.
Internally VB uses Unicode ("wide") characters, whereas the NAG C Library uses ASCII. VB handles the conversion from Unicode to ASCII for function/subroutine arguments but not for strings in structures. Therefore, some C strings are declared as Byte arrays in the VB header file. These VB strings need to be copied to and from the Byte arrays.
To copy a C null terminated string to a VB String, e.g. the fail.message Byte array in the NAG error structure:
Dim fail As New NagError Dim strResult As New StringBuilder Dim enc As New System.Text.ASCIIEncoding ... strResult.Append("e04cbc failed with error code " & enc.GetString(fail.message))
Or, to copy a VB String to an optional Byte array parameter to a NAG C Library function:
Dim filename As New StringBuilder Dim options As New Nag_E04_Opt Dim enc As New System.Text.ASCIIEncoding ... filename.Append("C:\e04dgce_output.r") ' Pad the end of filename with null character filename.Length = NAG_FILE_LEN ' Encode filename into a sequence of bytes options.outfile = enc.GetBytes(filename.ToString)
Arrays of strings are declared as IntPtr arrays. VB String arrays can be copied to IntPtr arrays using the StringToHGlobalAnsi method of the Marshal class:
Dim ch() As String Dim ch_ptr_array() As IntPtr ... For i = 0 To ch.Length - 1 ch_ptr_array(i) = Marshal.StringToHGlobalAnsi(ch(i)) Next i index = m01ncc(..., ch_ptr_array, ...)
An array of pointers to null terminated strings returned from a C Library function can be processed using the PtrToStringAnsi method of the Marshal class:
Dim model_ptr_array() As IntPtr Dim model_str() As String ... Call g02eec(..., model_ptr_array, ...) For i = 0 To maxip - 1 model_str(i) = Marshal.PtrToStringAnsi(model_ptr_array(i)) Next i
See e04gdc, m01ncc and various routines within the MiscFunctions project for examples of these.
A number of NAG C Library functions, by default, create a console window to display intermediate results, etc.
Alternatively, this output may be redirected to a file as may be seen in the e04dgc example or suppressed entirely as may be seen in the e04nfc example.
The console window may be closed temporarily (until more output arrives) via File | Close or permanently (until the next time the application is invoked) via File | Exit. Closing the console window from the close button ("X") in the top right hand corner or via
(The Excel/VBA e04ucc example uses this feature.)