// mvdll.cpp source code
#include <windows.h> // CF_TEXT
#define MV_UTILITIES // one per project
#include "mvdll.h" // this includes dllinter.h
// function names (to be added to the MathViews engine)
static char *FunctionNames [] =
{
"mvdlladd", //MVDLL_ADD 0
"mvdllmul", //MVDLL_MUL 1
"mvdllconcat", //MVDLL_CONCATSTR 2
"mvdllmax", //MVDLL_MAX 3
"mvdll_donothing", //MVDLL_DONOTHING 4
0
};
static HANDLE DllInst = NULL; // Dll Instance
static void *mvDLL = NULL; // pointer to class
extern "C" {
/************************************************************************
*
* "DllMain" This is the Main entry point for windows NT,
* and is called when the library is loaded.
*
*
* INPUTS:
* hInstance = DLLs instance handle
* dwReason = Reason why DllMain is being called
* lpReserved = additional status of "PROCESS" calls
*
*
* RETURNS:
* "DLL_PROCESS_ATTACH"
* TRUE if the initialization is successful;
* FALSE for error, abort.
* else
* ignored.
*
*************************************************************************/
BOOL WINAPI DllMain( HANDLE hInstance, DWORD dwReason, LPVOID lpReserved )
{
// save our instance handle
DllInst = hInstance;
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
return (TRUE); // successful attach!
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return (FALSE);
}
//----------------------------------------------------------------------
/* Interface between DLL and application */
int WINAPI InitMathViewsDll ( MV_INTERFACE *mv, char ***Names) // OUTPUT
{
mvDLL = (void *) (new MvDll(mv));
*Names = FunctionNames;
return TRUE;
}
int WINAPI ExecMathViewsDll (
void * program,
int type,
int * nout,
Datum ** dat_out,
int nin,
Datum ** dat_in)
{
if (type == -1)
{
strcpy ((char *) dat_out, "MVDDEV1.11"); //SH 4/21/93
return TRUE;
}
return ((MvDll *)mvDLL)->DllFunction(type, nout, dat_out, nin, dat_in);
}
int WINAPI AbortMathViewsDll ( void* )
{
((MvDll *)mvDLL)->Abort ();
return TRUE;
}
int WINAPI CloseMathViewsDll ( void* )
{
delete (MvDll *)mvDLL;
return TRUE;
}
} // extern "C"
MvDll::~MvDll()
{
// cleanup code
if (Initialized)
{
// cleanup code
}
}
MvDll::MvDll(MV_INTERFACE *mv)
{
memcpy (&MV, mv, sizeof (MV));
Initialized = FALSE;
}
int MvDll::DllFunction (
int type,
int * nout,
Datum ** dat_out,
int nin,
Datum ** dat_in)
{
*nout = 0;
if (Initialized == FALSE)
{
// perform initialization (if needed)
Initialized = TRUE;
}
switch (type)
{
case MVDLL_ADD :
if ( nin != 2 ||
!MVIsArray(dat_in[0]) ||
!MVIsArray(dat_in[1]) )
{
IssueError (ARG_ERROR, "arg error");
break;
}
ReadArg(dat_in[0], Arg1);
ReadArg(dat_in[1], Arg2);
AddArgs(dat_out[0]);
break;
case MVDLL_MUL :
if ( nin != 2 ||
!MVIsArray(dat_in[0]) ||
!MVIsArray(dat_in[1]) )
{
IssueError (ARG_ERROR, "arg error");
break;
}
ReadArg(dat_in[0], Arg1);
ReadArg(dat_in[1], Arg2);
MulArgs(dat_out[0]);
break;
case MVDLL_CONCATSTR :
if ( nin != 2 ||
!MVIsArray(dat_in[0]) ||
!MVIsArray(dat_in[1]) )
{
IssueError (ARG_ERROR, "arg error");
break;
}
ReadArg(dat_in[0], Arg1);
ReadArg(dat_in[1], Arg2);
ConcatArgs(dat_in[0], dat_in[1], dat_out[0]);
break;
case MVDLL_MAX :
if ( nin != 1 ||
!MVIsArray(dat_in[0]) )
{
IssueError (ARG_ERROR, "arg error");
break;
}
ReadArg(dat_in[0], Arg1);
MaxArg(dat_out[0]);
break;
case MVDLL_DONOTHING :
DoNothing(dat_out[0]);
break;
}
if(dat_out[0] && *nout == 0)
*nout = 1;
return TRUE;
}
void MvDll::Abort ()
{
// abort current execution
}
void MvDll::ReadArg(Datum *d, MvArg &arg)
{
(* MV.MVArrayInfo)(MV.Program, d->u.a, &arg.pval, &arg.m, &arg.n, &arg.type);
}
int MvDll::StringOf(Datum *d, char *buf, int len)
{
MvArg arg;
INDINT i;
int nSuccess = FALSE;
if (MVIsString (d))
{
ReadArg(d, arg);
// convert data to string
for (i = 0; i < arg.m * arg.n && i < len-1; i++, arg.pval++)
buf [i] = (char) *arg.pval;
buf [i] = '\0';
nSuccess = TRUE;
}
else
IssueError(BAD_ARGUMENT, "bad argument");
return nSuccess;
}
// add the two arguments (ignoring shape) and return the data
// in a matrix same shape as Arg1
// It also demonstrates handling of a complex arguments (we only
// deal with real+real and complex+complex
// it is fairly easy (and tedious) to deal with complex+real cases
int MvDll::AddArgs(Datum *&dout)
{
INDINT i, nm1, nm2, iRow = 0;
int nSuccess = FALSE;
double dAdd;
int cplxSize = 2; // Complex size in doubles
double dAddReal, dAddImag;
nm1 = Arg1.m * Arg1.n;
nm2 = Arg2.m * Arg2.n;
if(nm1 != nm2)
{
IssueError(BAD_ARGUMENT, "size mismatch");
goto FuncExit;
}
if(!dout)
{
dout = (*MV.MVNewDatum)(MV.Program);
if(!dout)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
}
dout->Type = DARRAY;
dout->u.a = (*MV.MVNewArray)(MV.Program, Arg1.m, Arg1.n, Arg1.type);
if(!dout->u.a)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
switch(Arg1.type)
{
case REAL_TYPE:
if(Arg2.type != REAL_TYPE)
{
IssueError(BAD_ARGUMENT, "can add only real to real");
goto FuncExit;
}
// now add the elements
for(i = 0; i < nm1; i++)
{
dAdd = Arg1.pval[i]+Arg2.pval[i];
MVSetElement(&MV, dout->u.a, i, iRow, dAdd);
}
break;
case COMPLEX_TYPE:
if(Arg2.type != COMPLEX_TYPE)
{
IssueError(BAD_ARGUMENT, "can add only complex to complex");
goto FuncExit;
}
nm1 *= cplxSize;
// now add the elements
for(i = 0; i < nm1; i += cplxSize)
{
dAddReal = Arg1.pval[i]+Arg2.pval[i];
dAddImag = Arg1.pval[i+1]+Arg2.pval[i+1];
MVSetComplexElement(&MV, dout->u.a, i, iRow, dAddReal, dAddImag);
}
break;
default:
{
IssueError(BAD_ARGUMENT, "unknown type");
goto FuncExit;
}
break;
}
nSuccess = TRUE;
FuncExit:
return nSuccess;
}
// multiply the two arguments (ignoring shape)
// return the data in a row vector
int MvDll::MulArgs(Datum *&dout)
{
INDINT i, nm1, nm2, iRow = 0;
int nSuccess = FALSE;
double dMul;
nm1 = Arg1.m * Arg1.n;
nm2 = Arg2.m * Arg2.n;
if(nm1 != nm2)
{
IssueError(BAD_ARGUMENT, "size mismatch");
goto FuncExit;
}
if(!dout)
{
dout = (*MV.MVNewDatum)(MV.Program);
if(!dout)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
}
dout->Type = DARRAY;
dout->u.a = (*MV.MVNewArray)(MV.Program, 1, nm2, REAL_TYPE);
if(!dout->u.a)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
// now multiply the elements
for(i = 0; i < nm1; i++)
{
dMul = Arg1.pval[i]*Arg2.pval[i];
MVSetElement(&MV, dout->u.a, i, iRow, dMul);
}
nSuccess = TRUE;
FuncExit:
return nSuccess;
}
// concat the two arguments
int MvDll::ConcatArgs(Datum *&d1, Datum *&d2, Datum *&dout)
{
INDINT iRow, jCol;
int nSuccess = FALSE;
double dAdd = 0.0;
if(Arg1.m != Arg2.m)
{
IssueError(BAD_ARGUMENT, "size mismatch");
goto FuncExit;
}
if(!dout)
{
dout = (*MV.MVNewDatum)(MV.Program);
if(!dout)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
}
dout->Type = DARRAY;
dout->u.a = (*MV.MVNewArray)(MV.Program, Arg1.m, Arg1.n+Arg2.n, REAL_TYPE);
if(!dout->u.a)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
// now concat the elements
for(iRow = 0; iRow < Arg1.m; iRow++)
{
for(jCol = 0; jCol < Arg1.n; jCol++)
{
dAdd = MVGetElement (&MV, d1->u.a, jCol, iRow);
MVSetElement(&MV, dout->u.a, jCol, iRow, dAdd);
}
}
for(iRow = 0; iRow < Arg2.m; iRow++)
{
for(jCol = 0; jCol < Arg2.n; jCol++)
{
dAdd = MVGetElement (&MV, d2->u.a, jCol, iRow);
MVSetElement(&MV, dout->u.a, Arg1.n+jCol, iRow, dAdd);
}
}
nSuccess = TRUE;
FuncExit:
return nSuccess;
}
// return the max of all elements in the argument
int MvDll::MaxArg(Datum *&dout)
{
INDINT i, nm1;
int nSuccess = FALSE;
double dMax;
nm1 = Arg1.m * Arg1.n;
if(!dout)
{
dout = (*MV.MVNewDatum)(MV.Program);
if(!dout)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
}
dout->Type = DARRAY;
dout->u.a = (*MV.MVNewArray)(MV.Program, 1, 1, REAL_TYPE);
if(!dout->u.a)
{
IssueError(BAD_ARGUMENT, "memory error");
goto FuncExit;
}
// find the max value
dMax = Arg1.pval[0];
for(i = 1; i < nm1; i++)
{
if(dMax < Arg1.pval[i])
dMax = Arg1.pval[i];
}
MVSetElement(&MV, dout->u.a, 0, 0, dMax);
nSuccess = TRUE;
FuncExit:
return nSuccess;
}
// calls some function for side effects (Initialize hardware,
// start FTP transfer, etc.). No return argument
int MvDll::DoNothing(Datum *&dout)
{
int nSuccess = FALSE;
return nSuccess;
}
void MvDll::IssueError (int Code, char *msg)
{
(*MV.MVError) (MV.Program, Code, msg); //Code defined in header interface
}