// MatlabInterfacingEngineDoc.cpp : implementation of the CMatlabInterfacingEngineDoc class
//
#include "stdafx.h"
#include "MatlabInterfacingEngine.h"
#include "MatlabInterfacingEngineDoc.h"
#include "MatlabInterfacingEngineView.h"
#include <BasicClasses\Include\CEditOutputStream.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMatlabInterfacingEngineDoc
IMPLEMENT_DYNCREATE(CMatlabInterfacingEngineDoc, CDocument)
BEGIN_MESSAGE_MAP(CMatlabInterfacingEngineDoc, CDocument)
//{{AFX_MSG_MAP(CMatlabInterfacingEngineDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CMatlabInterfacingEngineDoc, CDocument)
//{{AFX_DISPATCH_MAP(CMatlabInterfacingEngineDoc)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "getLastOutput", getLastOutput, VT_BSTR, VTS_NONE)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "evaluateString", evaluateString, VT_I2, VTS_BSTR)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "putScalar", putScalar, VT_I2, VTS_BSTR VTS_VARIANT)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "putArray", putArray, VT_I2, VTS_BSTR VTS_VARIANT)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "putMatrix", putMatrix, VT_I2, VTS_BSTR VTS_VARIANT)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "getScalar", getScalar, VT_I2, VTS_BSTR VTS_PVARIANT)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "getArray", getArray, VT_I2, VTS_BSTR VTS_PVARIANT VTS_PI2)
DISP_FUNCTION(CMatlabInterfacingEngineDoc, "getMatrix", getMatrix, VT_I2, VTS_BSTR VTS_PVARIANT VTS_PI2 VTS_PI2)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
// Note: we add support for IID_IMatlabInterfacingEngine to support typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .ODL file.
// {889CAFA3-5B18-4246-88C1-3ED71B61BCA3}
static const IID IID_IMatlabInterfacingEngine =
{ 0x889cafa3, 0x5b18, 0x4246, { 0x88, 0xc1, 0x3e, 0xd7, 0x1b, 0x61, 0xbc, 0xa3 } };
BEGIN_INTERFACE_MAP(CMatlabInterfacingEngineDoc, CDocument)
INTERFACE_PART(CMatlabInterfacingEngineDoc, IID_IMatlabInterfacingEngine, Dispatch)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMatlabInterfacingEngineDoc construction/destruction
//
CMatlabInterfacingEngineDoc::CMatlabInterfacingEngineDoc()
{
pView=NULL;
pEngine=NULL;
EnableAutomation();
AfxOleLockApp();
pEngine=engOpen(NULL);
engSetVisible(pEngine,0);
engOutputBuffer(pEngine,matlabBuffer,matlabBufferLength);
statementCounter=1;
}
//
CMatlabInterfacingEngineDoc::~CMatlabInterfacingEngineDoc()
{
if( pEngine!=NULL ) engClose( pEngine );
AfxOleUnlockApp();
}
//
BOOL CMatlabInterfacingEngineDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
((CEditView*)m_viewList.GetHead())->SetWindowText(NULL);
POSITION pos=GetFirstViewPosition();
CView* p=GetNextView(pos);
ASSERT( p->IsKindOf(RUNTIME_CLASS(CMatlabInterfacingEngineView)) );
pView=(CMatlabInterfacingEngineView *)p;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMatlabInterfacingEngineDoc serialization
void CMatlabInterfacingEngineDoc::Serialize(CArchive& ar)
{
// CEditView contains an edit control which handles all serialization
((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
}
/////////////////////////////////////////////////////////////////////////////
// CMatlabInterfacingEngineDoc diagnostics
#ifdef _DEBUG
void CMatlabInterfacingEngineDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CMatlabInterfacingEngineDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMatlabInterfacingEngineDoc commands
using namespace kaBasicClasses;
using namespace std;
//
BSTR CMatlabInterfacingEngineDoc::getLastOutput()
{
CString strResult;
matlabBuffer[matlabBufferLength]=char(0);
strResult=CString(matlabBuffer);
return strResult.AllocSysString();
}
//
short CMatlabInterfacingEngineDoc::evaluateString(LPCTSTR statement)
{
if( pView==NULL )
{
if( pEngine!=NULL && engEvalString(pEngine,(const char*)statement)==0 )
return 0;
else
return 1;
}
else
{
CEditOutputStream os(&(pView->GetEditCtrl()));
os.setCursorAtEnd();
os<<endl<<"Call via COM response."<<endl;
os<<endl<<"Processing the statement"<<endl;
os<<(const char*)statement<<endl;
os.flush();
if( pEngine!=NULL && engEvalString(pEngine,(const char*)statement)==0 )
{
matlabBuffer[matlabBufferLength]=char(0);
os<<endl<<matlabBuffer<<endl;
return 0;
}
else
{
os<<endl<<"Matlab engine is not running"<<endl;
return 1;
}
}
}
//
short CMatlabInterfacingEngineDoc::putScalar(LPCTSTR name, const VARIANT FAR& value)
{
CEditOutputStream* os=NULL;
short ret=0;
if( pView!=NULL )
{
os=new CEditOutputStream(&(pView->GetEditCtrl()));
os->setCursorAtEnd();
}
if( pEngine==NULL )
{
if( os!=NULL )
(*os)<<"Matlab engine is not running."<<endl;
ret++;
}
else
{
if( os!=NULL )
{
(*os)<<endl<<"Call via COM response."<<endl;
(*os)<<endl<<"Introducing a scalar:"<<endl;
os->flush();
}
mxArray* mxValue=NULL;
switch( value.vt )
{
case VT_I2:
mxValue=mxCreateScalarDouble(value.iVal);
break;
case VT_I4:
mxValue=mxCreateScalarDouble(value.lVal);
break;
case VT_R4:
mxValue=mxCreateScalarDouble(value.fltVal);
break;
case VT_R8:
mxValue=mxCreateScalarDouble(value.dblVal);
break;
case VT_I1:
mxValue=mxCreateScalarDouble(value.cVal);
break;
case VT_UI2:
mxValue=mxCreateScalarDouble(value.uiVal);
break;
case VT_UI4:
mxValue=mxCreateScalarDouble(value.ulVal);
break;
case VT_INT:
mxValue=mxCreateScalarDouble(value.intVal);
break;
case VT_UINT:
mxValue=mxCreateScalarDouble(value.uintVal);
break;
default:
ret++;
break;
}
if( mxValue==NULL )
ret++;
else
{
ret=engPutVariable(pEngine,(const char*)name,mxValue);
mxDestroyArray(mxValue);
}
if( os!=NULL )
{
os->setCursorAtEnd();
if( ret==0 )
(*os)<<(const char*)name<<" = ... "<<endl;
else
(*os)<<"failed."<<endl;
os->flush();
}
matlabBuffer[0]=char(0);
}
if( os!=NULL )
delete os;
return ret;
}
//
short CMatlabInterfacingEngineDoc::putArray(LPCTSTR name, const VARIANT FAR& value)
{
CEditOutputStream* os=NULL;
short ret=0;
if( pView!=NULL )
{
os=new CEditOutputStream(&(pView->GetEditCtrl()));
os->setCursorAtEnd();
}
if( pEngine==NULL )
{
if( os!=NULL )
(*os)<<"Matlab engine is not running."<<endl;
ret++;
}
else
{
if( os!=NULL )
{
(*os)<<endl<<"Call via COM response."<<endl;
(*os)<<endl<<"Introducing an array:"<<endl;
os->flush();
}
mxArray* mxValue=NULL;
switch( value.vt )
{
case VT_ARRAY|VT_BYREF|VT_R8:
{
double* pr=(double *)(*(value.pparray))->pvData;
switch( (*(value.pparray))->cDims )
{
case 1:
{
unsigned long n=(*(value.pparray))->rgsabound[0].cElements;
mxValue=mxCreateDoubleMatrix(1,n,mxREAL);
if( mxValue==NULL )
{
if( os!=NULL )
{
(*os)<<endl<<"Out-of-memory"<<endl;
delete os;
}
ret++;
return ret;
}
copy( pr, pr+n, mxGetPr(mxValue) );
}
break;
case 2:
{
unsigned long n=(*(value.pparray))->rgsabound[0].cElements;
unsigned long m=(*(value.pparray))->rgsabound[1].cElements;
int N=n*m;
mxValue=mxCreateDoubleMatrix(1,N,mxREAL);
if( mxValue==NULL )
{
if( os!=NULL )
{
(*os)<<endl<<"Out-of-memory"<<endl;
delete os;
}
ret++;
return ret;
}
copy( pr, pr+N, mxGetPr(mxValue) );
}
break;
case 3:
{
unsigned long n=(*(value.pparray))->rgsabound[0].cElements;
unsigned long m=(*(value.pparray))->rgsabound[1].cElements;
unsigned long k=(*(value.pparray))->rgsabound[2].cElements;
int N=n*m*k;
mxValue=mxCreateDoubleMatrix(1,N,mxREAL);
if( mxValue==NULL )
{
if( os!=NULL )
{
(*os)<<endl<<"Out-of-memory"<<endl;
delete os;
}
ret++;
return ret;
}
copy( pr, pr+N, mxGetPr(mxValue) );
}
break;
default:
ret++;
}
}
break;
default:
ret++;
break;
}
if( ret==0 )
ret=engPutVariable(pEngine,(const char*)name,mxValue);
if( mxValue!=NULL )
mxDestroyArray(mxValue);
if( os!=NULL )
{
os->setCursorAtEnd();
if( ret==0 )
(*os)<<(const char*)name<<" = [ ... ] "<<endl;
else
(*os)<<"failed."<<endl;
os->flush();
}
matlabBuffer[0]=char(0);
}
if( os!=NULL )
delete os;
return ret;
}
//
short CMatlabInterfacingEngineDoc::putMatrix(LPCTSTR name, const VARIANT FAR& value)
{
CEditOutputStream* os=NULL;
short ret=0;
if( pView!=NULL )
{
os=new CEditOutputStream(&(pView->GetEditCtrl()));
os->setCursorAtEnd();
}
if( pEngine==NULL )
{
if( os!=NULL )
(*os)<<"Matlab engine is not running."<<endl;
ret++;
}
else
{
if( os!=NULL )
{
(*os)<<endl<<"Call via COM response."<<endl;
(*os)<<endl<<"Introducing a matrix:"<<endl;
os->flush();
}
mxArray* mxValue=NULL;
switch( value.vt )
{
case VT_ARRAY|VT_BYREF|VT_R8:
{
double* pr=(double *)(*(value.pparray))->pvData;
switch( (*(value.pparray))->cDims )
{
case 1:
{
unsigned long n=(*(value.pparray))->rgsabound[0].cElements;
mxValue=mxCreateDoubleMatrix(1,n,mxREAL);
if( mxValue==NULL )
{
if( os!=NULL )
{
(*os)<<endl<<"Out-of-memory"<<endl;
delete os;
}
ret++;
return ret;
}
copy( pr, pr+n, mxGetPr(mxValue) );
}
break;
case 2:
{
unsigned long n=(*(value.pparray))->rgsabound[0].cElements;
unsigned long m=(*(value.pparray))->rgsabound[1].cElements;
mxValue=mxCreateDoubleMatrix(m,n,mxREAL);
if( mxValue==NULL )
{
if( os!=NULL )
{
(*os)<<endl<<"Out-of-memory"<<endl;
delete os;
}
ret++;
return ret;
}
copy( pr, pr+n*m, mxGetPr(mxValue) );
}
break;
default:
ret++;
}
}
break;
default:
ret++;
break;
}
if( ret==0 )
ret=engPutVariable(pEngine,(const char*)name,mxValue);
if( mxValue!=NULL )
mxDestroyArray(mxValue);
if( os!=NULL )
{
os->setCursorAtEnd();
if( ret==0 )
(*os)<<(const char*)name<<" = [ ... ] "<<endl;
else
(*os)<<"failed."<<endl;
os->flush();
}
matlabBuffer[0]=char(0);
}
if( os!=NULL )
delete os;
return ret;
}
//
short CMatlabInterfacingEngineDoc::getScalar(LPCTSTR name, VARIANT FAR* putHere)
{
if( pEngine==NULL )
return 1;
mxArray* theArray=engGetVariable(pEngine,(const char *)name);
if( theArray==NULL )
return 2;
VariantClear(putHere);
putHere->vt=VT_R8;
putHere->dblVal=mxGetPr(theArray)[0];
mxDestroyArray(theArray);
return 0;
}
#define DIM1 1
#define DIM2 2
//
short CMatlabInterfacingEngineDoc::getArray(LPCTSTR name, VARIANT FAR* putHere, short FAR* dim)
{
if( pEngine==NULL )
return 1;
mxArray* theArray=engGetVariable(pEngine,(const char *)name);
if( theArray==NULL )
return 2;
VariantClear(putHere);
putHere->vt=VT_ARRAY|VT_R8;
switch( mxGetNumberOfDimensions(theArray) )
{
case DIM1:
{
const int* n=mxGetDimensions(theArray);
SAFEARRAYBOUND rgsabound[DIM1];
rgsabound[0].lLbound=0;
rgsabound[0].cElements=n[0];
putHere->parray=SafeArrayCreate(VT_R8,DIM1,rgsabound);
if( putHere->parray==NULL )
{
mxDestroyArray(theArray);
return 4;
}
copy(
mxGetPr(theArray), mxGetPr(theArray)+n[0],
(double *)(putHere->parray->pvData)
);
*dim=n[0];
}
break;
case DIM2:
{
const int* n=mxGetDimensions(theArray);
SAFEARRAYBOUND rgsabound[DIM1];
rgsabound[0].lLbound=0;
rgsabound[0].cElements=n[0]*n[1];
putHere->parray=SafeArrayCreate(VT_R8,DIM1,rgsabound);
if( putHere->parray==NULL )
{
mxDestroyArray(theArray);
return 4;
}
copy(
mxGetPr(theArray), mxGetPr(theArray)+n[0]*n[1],
(double *)(putHere->parray->pvData)
);
*dim=n[0]*n[1];
}
break;
default:
mxDestroyArray(theArray);
return 3;
}
mxDestroyArray(theArray);
return 0;
}
//
short CMatlabInterfacingEngineDoc::getMatrix(LPCTSTR name, VARIANT FAR* putHere, short FAR* rows, short FAR* cols)
{
if( pEngine==NULL )
return 1;
mxArray* theArray=engGetVariable(pEngine,(const char *)name);
if( theArray==NULL )
return 2;
VariantClear(putHere);
putHere->vt=VT_ARRAY|VT_R8;
switch( mxGetNumberOfDimensions(theArray) )
{
case DIM1:
{
const int* n=mxGetDimensions(theArray);
SAFEARRAYBOUND rgsabound[DIM1];
rgsabound[0].lLbound=0;
rgsabound[0].cElements=n[0];
putHere->parray=SafeArrayCreate(VT_R8,DIM1,rgsabound);
if( putHere->parray==NULL )
{
mxDestroyArray(theArray);
return 4;
}
copy(
mxGetPr(theArray), mxGetPr(theArray)+n[0],
(double *)(putHere->parray->pvData)
);
*rows=1;
*cols=n[0];
}
break;
case DIM2:
{
const int* n=mxGetDimensions(theArray);
SAFEARRAYBOUND rgsabound[DIM1];
rgsabound[0].lLbound=0;
rgsabound[0].cElements=n[0]*n[1];
putHere->parray=SafeArrayCreate(VT_R8,DIM1,rgsabound);
if( putHere->parray==NULL )
{
mxDestroyArray(theArray);
return 4;
}
copy(
mxGetPr(theArray), mxGetPr(theArray)+n[0]*n[1],
(double *)(putHere->parray->pvData)
);
*rows=n[0];
*cols=n[1];
}
break;
default:
mxDestroyArray(theArray);
return 3;
}
mxDestroyArray(theArray);
return 0;
}