Sample Microsoft Visual Basic .NET 64-bit Projects Illustrating How to Call the NAG C Library Mark 23
This folder contains a number of subfolders, each containing a Microsoft Visual Basic .NET project showing how to call a 64-bit NAG C Library function. These projects have been built and tested under Visual Studio 2005 and also tested with Visual Studio 2008, Visual Studio 2010 and Visual Studio 2012. They should run without modification under Visual Studio 2005. To run these projects under Visual Studio 2008, Visual Studio 2010 or Visual Studio 2012, use the Visual Studio conversion wizard to convert the project. This will update the .sln and .vbproj files; the VB code itself should remain the same. There are separate examples showing how to call the Library from 64-bit Excel 2010 using Visual Basic for Applications 7.0 (VBA7).
- misc_functions.zip (includes examples for s17dgc, e04ccc, f04cec, f04cfc, a00aac, x04nac & x04nbc, s15ddc and m01csc)
Note that where a project uses data files, these may be found in the bin subfolder for that project.
A support file for 64-bit Visual Basic .NET (VB.NET), called clvbdnet64.vb, may be found under the VB.NET 64-bit headers page. This file can be used in 64-bit VB.NET code. Separate VBA7 headers are available for use with 64-bit Excel Visual Basic for Applications.
The file clvbdnet64.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 (CLW6I23DA_nag.dll); to specify the version of the DLL which uses the MKL BLAS/LAPACK instead (CLW6I23DA_mkl.dll), replace CLW6I23DA_nag.dll by CLW6I23DA_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\CL23\clw6i23dal\bin (for example), then your PATH environment variable must contain this folder before starting Visual Basic. If you are using the MKL-based version of the NAG C Library (CLW6I23DA_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\CL23\clw6i23dal\bin;C:\Program Files\NAG\CL23\ clw6i23dal\MKL_intel64_10.3\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 e04ccc Lib "CLW6I23DA_nag.dll" ( _ ..., <[In](),Out()> ByVal x As Double(), ... ... Dim x(n - 1) As Double ... Call e04ccc(..., 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 "CLW6I23DA_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 "CLW6I23DA_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 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, e04nfc and in the e04ccce 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 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)
This usage is illustrated in the e04ccce code within the MiscFunctions example.
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("e04ccc 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:\e04ccce_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
Output strings are declared as IntPtr. A string returned from a C Library function as IntPtr can be copied to a VB String using the PtrToStringAnsi method of the Marshal class:
Dim teststr As String Dim strptr As IntPtr ... strptr = x04nbc(testnum) teststr = Marshal.PtrToStringAnsi(strptr)
See 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 e04ccc example within the MiscFunctions project, 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 Alt-F4 has the same effect as File | Close. There are also cut, copy and paste facilities available via the Edit menu.
(The Excel/VBA7 e04ucc example uses this feature.)