// 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 }