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
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.
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.
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.
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.