C example

File 1 and File 2 are bound together to create application A. File 1 is compiled with the NODLL option. File 2 is compiled with the DLL option (so that it can call the DLL function sort()). File 3 is compiled as DLL to create application B. Application A and B can both call the imported function sort() from the DLL in file 4.

Figure 1 shows how a file (File 1) of a complex DLL application is compiled with the NODLL option

Figure 1. File 1. Application A
typedef int CmpFP(int, int);
void sort(int* arr, int size, CmpFP*);         /* sort routine in DLL        */
void callsort(int* arr, int size, CmpFP* fp);  /* routine compiled as DLL    */
                                               /* which can call DLL         */
                                               /* routine sort()             */
int comp(int e1, int e2) {
  if (e1 == e2) {
    return(0);
  }
  else if (e1 < e2) {
    return(-1);
  }
  else {
    return(1);
  }
}

main() {
  CmpFP* fp = comp;
  int a[2] = {2,1};
  callsort(a, 2, fp);
  return(0);
}

Figure 2 shows how a file (File 2) of a complex DLL application is compiled with the DLL option.

Figure 2. File 2. Application A
typedef int CmpFP(int, int);
void sort(int* arr, int size, CmpFP*);         /* sort routine in DLL       */
void callsort(int* arr, int size, CmpFP* fp) {
  sort(arr, size, fp);
}

Figure 3 shows how a simple DLL application is compiled with the DLL option.

Figure 3. File 3. Application B
int comp(int e1, int e2) {
  if (e1 == e2)
    return(0);
  else if (e1 < e2)
    return(-1);
  else
    return(1); }
int (*fp)(int e1, int e2);
main()
{
  int a[2] = { 2, 1 };
  fp = comp;       /* assign function address */
  sort(a, 2, fp); /* call sort */
}

Figure 4 shows how a DLL is compiled with the NODLL option. File 4 is compiled as NODLL and bound into a DLL. The function sort() will be exported to users of the DLL.

Figure 4. File 4. DLL
typedef int CmpFP(int, int);
int sort(int* arr, int size, CmpFP* fp) {
  int i,j,temp,rc;

  for (i=0; i<size; ++i) {
    for (j=1; j<size-1; ++j) {
      rc = fp(arr[j-1], arr[j]); /* call 'fp' which may be DLL or no-DLL code */
      if (rc > 0) {
        temp     = arr[j];
        arr[j]   = arr[j-1];
        arr[j-1] = temp;
      }
    }
  }
  return(0);
}
#pragma export(sort)

Non-DLL function pointers can only safely be passed to a DLL if the function referenced is naturally reentrant, that is, it is C code compiled with the RENT compiler option, or is C code with no global or static variables. See the discussion on the CBA option to see how to make a DLL that can be called by applications that pass constructed reentrant function pointers.

Figure 5. DLL function pointer call in non-DLL code
Graphic DLL function pointer call in non-DLL code