Code Structure

Parent Previous Next

Code Structure.

The C# code basically consists of 4 parts:

1.

The class definition in general and a public delegate that constitutes a prototype of the callback function.

2.

Private functions that encapsulate the native DLL API.

3.

Private support-functions that assist with certain type conversions and provide error management.

4.

Public functions that resemble the @VMxxxx library functions.


All functions are static, meaning they can be used as shared/global functions with no dependency to any instantiated object.  


1. The Class and Delegate.

The class is named DLL and is part of the name space DLL_Interface:



namespace DLL_Interface

{

   [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

   public delegate Int32 TCallBack(Int32 x, Int32 y, Int32 z);


   class DLL

   {

       //...

   }

}



Besides the class we also have the delegate that defines the callback prototype. It is here presented with the cdecl calling convention, but please note it must use the same calling convention as specified for the function _VMSetCallback.


2. Encapsulation of API Functions.

All native DLL API functions are completely encapsulated as private functions.


Here is an example of encapsulating the API function VMFree_cdecl based on the cdecl calling convention:



       private const string DLLNAME = "VM32.dll";


       //Specifies how to access the API function VMFree_cdecl as a private method named _VMFree.

       [DllImport(DLLNAME, EntryPoint = "VMFree_cdecl", CallingConvention = CallingConvention.Cdecl)]

       private static extern Int32 _VMFree(Int32 vm);



The rest of the API functions are encapsulated in a similar manner.


In case the stdcall calling convention is preferred, it should look like this:



       [DllImport(DLLNAME, EntryPoint = "VMFree", CallingConvention = CallingConvention.Stdcall)]

       private static extern Int32 _VMFree(Int32 vm);



Please note that the use of a string constant for the DLLNAME is just for convenience.


3. Support Functions.

As demonstrated later some assisting functionality is used quite a lot in many of the public functions. This additional functionality primarily supports two purposes:


4. Public Class Functions.

Most public functions share some commonalities which are represented nicely by the public function VMCellGetInteger:



       public static Int32 VMCellGetInteger(Int32 vm, Int32 row, Int32 col)

       {

           Int32 returnValue = 0;

           if (_VMCellGetInteger(vm, row, col, ref returnValue) != 1) RaiseLastError();

           return returnValue;

       }



This function is designed to have an argument signature and a return type similar to the library function @VMCellGetInteger.


It invokes the native DLL API function _VMCellGetInteger which passes the last argument returnValue by reference for an update. We check whether the function return 1 for success (alternatively 0 for error), and in case of failure, the method RaiseLastError is invoked.