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


Hosted by www.Geocities.ws

1