Calling C Library DLLs from C#
by Shah Datardina

Listing One

/***************************************************************
 *                     C Function  Scalars                     *
 ***************************************************************/
#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)

NAG_DLL_EXPIMP void NAG_CALL Scalars(double, double*);
NAG_DLL_EXPIMP void NAG_CALL Scalars(double in, double *out)
{
  *out = in;
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  public class ExerciseScalars
    {

      [DllImport("cmarshaldll")]
    public static extern void Scalars(double invar, ref double outvar);
      public static void CallScalars(double invar, ref double outvar)
    {
      Scalars(invar, ref outvar);
    }
      public static void Main()
    {
      double invar = 5.0;
      double outvar = 0.0;
      CallScalars(invar, ref outvar);
      Console.WriteLine("invar = {0}, outvar = {1}", invar, outvar);
    }
    }
}


Listing Two

/***************************************************************
 *                     C Function OneDArray                    *
 ***************************************************************/

#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)

NAG_DLL_EXPIMP void NAG_CALL OneDArray(int n, double []);
NAG_DLL_EXPIMP void NAG_CALL OneDArray(int n, double anArray[])
{
  int i;
  for (i=0; i<n; i++)
    anArray[i] = 99.0;
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/

using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  public class ExerciseOneDArray
    {
      [DllImport("cmarshaldll")]
    public static extern void OneDArray(int n, double [] anArray);
      
      public static void CallOneDArray(double [] anArray)
    {
      OneDArray(anArray.GetLength(0), anArray);
    }
      public static void Main()
    {
      int n=2;
      double [] anArray = new double [n];
      CallOneDArray(anArray);
      for (int i=0; i<n; i++)
        Console.WriteLine("{0}", anArray[i]);
    }
    }
}

Listing Three

/***************************************************************
 *                     C Function TwoDArray                    *
 ***************************************************************/

#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)
NAG_DLL_EXPIMP void NAG_CALL TwoDArray(int m, int n, double [], int tda);
#define A(I,J) a2dArray[I*tda+J]
NAG_DLL_EXPIMP void NAG_CALL TwoDArray(int m,int n,double a2dArray[],int tda)
{
  int i, j, k = 0;
  tda = n;
  for (i=0; i<m; i++)
    for (j=0; j<n; j++)
      {
    A(i,j) = ++k;
      }
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/

using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  public class ExerciseTwoDArray
    {
      [DllImport("cmarshaldll")]
        public static extern void TwoDArray(int m, int n, double [,] a2dArray,
                                            int tda);
      public static void CallTwoDArray(double [,] a2dArray)
        {
          TwoDArray(a2dArray.GetLength(0), a2dArray.GetLength(1),
                    a2dArray, a2dArray.GetLength(1));
        }
      public static void Main()
        {
          int m=3;
          int n=2;
          double [,] a2dArray = new double [m,n];
          CallTwoDArray(a2dArray);
          for (int i=0; i<m; i++)
            {
              for (int j=0; j<n; j++)
                Console.Write("{0}     ", a2dArray[i,j]);
              Console.WriteLine();
            }
        }
    }
}

Listing Four

/***************************************************************
 *                     C Function TryComplex                   *
 ***************************************************************/

#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)
  typedef struct {                /* NAG Complex Data Type */
    double re,im;
  } Complex;
NAG_DLL_EXPIMP void NAG_CALL TryComplex(Complex inputVar, Complex *outputVar,
                                             int n, Complex array[]);
NAG_DLL_EXPIMP void NAG_CALL TryComplex(Complex inputVar, Complex *outputVar, 
                                              int n, Complex array[])
{
  outputVar->re = ++inputVar.re;
  outputVar->im = ++inputVar.im;

  array[0].re = 99.0;
  array[0].im = 98.0;
  array[1].re = 97.0;
  array[1].im = 96.0;
  
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  // Nag Complex type
  [StructLayout(LayoutKind.Sequential)]
    public struct Complex
    {
      public double re;
      public double im;
    };
  public class ExerciseTryComplex
    {
      [DllImport("cmarshaldll")]
        public static extern void TryComplex(Complex inputVar, 
                ref Complex outputVar, int n, [In, Out]  Complex [] array);
      public static void CallTryComplex(Complex inputVar, 
                ref Complex outputVar, Complex [] array)
        {
          int n = 2;
      TryComplex(inputVar, ref outputVar, n, array);
        }
      public static void Main()
        {
          int n=2;
          Complex inputVar = new Complex();
          Complex outputVar = new Complex();
          Complex [] array = new Complex[n];
          inputVar.re = 1.0;
          inputVar.im = 2.0;
     CallTryComplex(inputVar, ref outputVar, array);
     Console.WriteLine("outputVar = ({0},{1})", outputVar.re, outputVar.im);
      Console.WriteLine("Array on output");
      for (int i = 0; i<array.GetLength(0); i++)
        Console.WriteLine("{0}  {1}", array[i].re, array[i].im);
        }
    }
}


Listing Five

/***************************************************************
 *                     C Function MarshalStructC               *
 ***************************************************************/
#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)

#include <stdlib.h>
  typedef struct
  {
    int array_length;
    double *array;
  } marshalStruct;
NAG_DLL_EXPIMP void NAG_CALL MarshalStructC(marshalStruct *pointerinStruct);
NAG_DLL_EXPIMP void NAG_CALL 
                       FreeMarshalStructptr(marshalStruct *pointerinStruct);
/**/
NAG_DLL_EXPIMP void NAG_CALL MarshalStructC(marshalStruct *pointerinStruct)
{
  int i;
  pointerinStruct->array = 
    (double *)malloc((size_t)(sizeof(double)*pointerinStruct->array_length));
  for (i = 0; i <pointerinStruct->array_length; i++)
    {
      pointerinStruct->array[i] = (double)(i) + 1.0;
    }
}
NAG_DLL_EXPIMP void NAG_CALL 
               FreeMarshalStructptr(marshalStruct *pointerinStruct)
{
  free(pointerinStruct->array);
  pointerinStruct->array = 0;
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  [StructLayout(LayoutKind.Sequential)]
    public struct marshalStruct
    {
      public int array_length;
      public IntPtr array;
    };
  public class ExerciseMarshalStructC
    {
      [DllImport("cmarshaldll")]
        public static extern void MarshalStructC(
                                         ref marshalStruct pointerinStruct);
      [DllImport("cmarshaldll")]
        public static extern void FreeMarshalStructptr(
                                         ref marshalStruct pointerinStruct);
      public static void CallMarshalStructC(ref marshalStruct pointerinStruct)
        {
          MarshalStructC(ref pointerinStruct);
        }
      public static void Main()
        {
          marshalStruct pointerinStruct = new  marshalStruct() ;
          pointerinStruct.array_length = 5;
          CallMarshalStructC(ref pointerinStruct);
          double [] x = new double[pointerinStruct.array_length];
          Marshal.Copy( pointerinStruct.array, x, 0, 
                                      pointerinStruct.array_length );
          for (int i = 0; i <  pointerinStruct.array_length; i++)
            Console.WriteLine("x[{0}] = {1}", i, x[i]);
      FreeMarshalStructptr(ref pointerinStruct);
        }
    }
}

Listing Six

/***************************************************************
 *                     C Function CallBack                     *
 ***************************************************************/

#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP __declspec(dllexport)

typedef void (NAG_CALL * NAG_D01_FUN)(double *);
NAG_DLL_EXPIMP void NAG_CALL CallBack(NAG_D01_FUN f , double *output);
NAG_DLL_EXPIMP void NAG_CALL f(double *x);

/* */
NAG_DLL_EXPIMP void NAG_CALL CallBack(NAG_D01_FUN f , double *output)
{
  (*f)(output);
}
NAG_DLL_EXPIMP void NAG_CALL f(double *x)
{
   *x = 100.0;
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  // delegate
  public delegate void  NAG_D01_FUN (ref double output);

  public class ExerciseSimpleCallback
    {
      [DllImport("cmarshaldll")]
        public static extern void CallBack(NAG_D01_FUN f , ref double output);
      public static void CallCallBack(NAG_D01_FUN f, ref double output)
        {
          CallBack(f, ref output);
        } 
      public static void Main()
        {
          double output = 0.0;
          NAG_D01_FUN F = new  NAG_D01_FUN (f);
          CallCallBack(F, ref output);
      Console.WriteLine("Ouput = {0}", output);
        }
      public static void f(ref double output)
        {
          output = 100.0;
        }
    }
}

Listing Seven

/***************************************************************
 *                     C Function  CallbackWithStruct          *
 ***************************************************************/
#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)

  typedef struct {
    int flag; 
  } Nag_Comm;
typedef void (NAG_CALL * NAG_E04UCC_FUN)(int, double *, Nag_Comm *);

extern NAG_DLL_EXPIMP void NAG_CALL CallbackWithStruct(NAG_E04UCC_FUN funct, 
                            int array_length, double *a, Nag_Comm *user_comm);
void NAG_CALL funct(int n, double *x, Nag_Comm *user_comm);

/* */
NAG_DLL_EXPIMP void NAG_CALL CallbackWithStruct(NAG_E04UCC_FUN funct , 
                                        int n, double *a, Nag_Comm *user_comm)
{
  (*funct)(n, a, user_comm);
  if (user_comm->flag == 99)
    {
      a[0] = 99.0;
    }
}
void NAG_CALL funct(int n, double *x, Nag_Comm *user_comm)
{
  int i;
  for (i=0; i<n; i++)
    {
      x[i]++;
    }
  if (x[0] < 3.0)
    {
      user_comm->flag = 99;
    }
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
namespace DDJexamples
{
  [StructLayout(LayoutKind.Sequential)]
    public struct Nag_Comm
    {
      public int flag;
    };
  // delegate
  public delegate void  NAG_E04UCC_FUN (int array_length, IntPtr a, 
                                                       ref Nag_Comm comm);
  public class ExerciseCallBackWithStruct
    {
      [DllImport("cmarshaldll")]
        public static extern void CallbackWithStruct(NAG_E04UCC_FUN f , 
                    int array_length, double [] a, ref Nag_Comm user_commt);
      public static void CallCallbackWithStruct(NAG_E04UCC_FUN f, 
                      int array_length, double [] a, ref Nag_Comm user_comm)
        {
          CallbackWithStruct(f, array_length, a, ref user_comm);
        } 
      public static void Main()
        {
      double []  a = {1.0, 2.0, 3.0, 4.0, 5.0};
      int array_length = a.GetLength(0);
      Nag_Comm user_comm = new Nag_Comm();
          NAG_E04UCC_FUN F = new  NAG_E04UCC_FUN (funct);
          CallCallbackWithStruct(F, array_length, a, ref user_comm);
      Console.WriteLine("user_comm.flag = {0}", user_comm.flag);
      Console.WriteLine("a[0] altered further as a result of 
                                       user_comm.flag, a[0] = {0}", a[0]);
        }
      public static void funct(int n, IntPtr xptr, ref Nag_Comm user_comm)
    {
    double [] x = new double[n];
    Marshal.Copy( xptr, x, 0, n );
     int i;
      for (i=0; i<n; i++)
        {
          x[i]++;
        }
      if (x[0] < 3.0)
        {
          user_comm.flag = 99;
        }
      Marshal.Copy( x, 0, xptr, n);

    }
    }
}

Listing Eight

/***************************************************************
 *                     C Function EnumString                   *
 ***************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define NAG_CALL __stdcall 
#define NAG_DLL_EXPIMP  __declspec(dllexport)

typedef enum { red=101, green, blue,black } colour;
NAG_DLL_EXPIMP void NAG_CALL EnumString(colour rainbow, char *rainbowcolour);
NAG_DLL_EXPIMP void NAG_CALL EnumString(colour rainbow, char *rainbowcolour)
{
  if (rainbow == black )
    {
      strcpy(rainbowcolour, "Black is not a rainbow colour");
    }
  else
    {
      strcpy(rainbowcolour, "This is a rainbow colour");
    }
}
/***************************************************************
 *                    C# Class                                 *
 ***************************************************************/
using System;
using System.Runtime.InteropServices; 
using System.Text;
namespace DDJexamples
{
  public  enum colour { red=101, green, blue,black };
  public class ExerciseEnumString
    {
      [DllImport("cmarshaldll")]
        public static extern void EnumString(colour rainbow, 
                                              StringBuilder rainbowcolour);

      public static void CallEnumString(colour rainbow, 
                                                StringBuilder rainbowcolour)
        {
          EnumString(rainbow, rainbowcolour);
        }
      public static void Main()
        {
          StringBuilder colourstring=
                                 new StringBuilder("once upon a time ... ");
          colour somecolour = colour.black;
          CallEnumString(somecolour, colourstring);
          Console.WriteLine("{0}", colourstring);
        }
    }
}





1


