|
I made some changes to the error handler so that I could see a description of the MATLAB errors that I get. Here is my modified version of ErrHandler:
<code>
void CMatlabEngine::ErrHandler(HRESULT hr, EXCEPINFO excep, UINT uArgErr)
{
USES_CONVERSION;
if (hr == DISP_E_EXCEPTION)
{
TCHAR errMsg[512];
::_stprintf(errMsg, TEXT("Run-time error %d:\n\n %s"),
excep.scode & 0x0000FFFF,
OLE2T(excep.bstrDescription));
::MessageBox(NULL, errMsg, TEXT("MATLAB Error"),
MB_SETFOREGROUND | MB_OK);
}
else
{
LPVOID lpMsgBuf;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr,
MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,
0, NULL);
if ((hr == DISP_E_TYPEMISMATCH ) ||
(hr == DISP_E_PARAMNOTFOUND))
{
TCHAR extMess[512];
::_stprintf(extMess, TEXT("%s Position of incorrect argument is %u.\n"), (LPCTSTR) lpMsgBuf, uArgErr);
::MessageBox(NULL, extMess, TEXT("COM Error"), MB_OK | MB_SETFOREGROUND);
}
else
{
::MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("COM Error"),MB_OK | MB_SETFOREGROUND);
}
::LocalFree(lpMsgBuf);
}
}
</code>
You must also add the following line to MatlabEngine.cpp:
<code>
#include <atlbase.h>
</code>
|
|
|
|
|
Thank you for the fix. I'll post an update of the source but it will take time to get to CP.
Jonathan de Halleux.
|
|
|
|
|
Thanks for this simple and very useful class.
The beautifully formatted doxygen documentation could be used as a reference for most programmers to learn from...
One small issue and one question:
In the article, you recommend checking IsInitialized() after instantiating the class, but you don't do this in the demo code.
And for the question:
We have a limited number of licenses at work. When you open matlab but can't get a license, you get a fatal error message box, and after you close it, matlab closes. Unfortunately, IsInitialized() returns true even when a license wasn't acquired. Is there any way to make sure that the app was really opened?
|
|
|
|
|
This is what I added to the demo code in InitInstance:
<br />
glob_pMatlab = new CMatlabEngine;<br />
if (!glob_pMatlab->IsInitialized()) {<br />
::MessageBox(NULL,"Can't initialize MATLAB","Fatal Error!",MB_OK);<br />
return FALSE;<br />
}
|
|
|
|
|
Thks (don't forget to vote )
arnonm wrote:
In the article, you recommend checking IsInitialized() after instantiating the class, but you don't do this in the demo code.
In fact, I'll fix that in the next release. Anyway, all methods of the wrapper check if it is initialized too...
arnonm wrote:
We have a limited number of licenses at work. When you open matlab but can't get a license, you get a fatal error message box, and after you close it, matlab closes. Unfortunately, IsInitialized() returns true even when a license wasn't acquired. Is there any way to make sure that the app was really opened?
You too... This damn software is not cheap and has a "very" dominant position on the math field.
I'm not very much into COM now... The key of the problem is "how to know if Matlab is open or not ???"
Anybody an idea?
Jonathan de Halleux.
|
|
|
|
|
Is the sample available in C#?
This sample works, but when I add the Reference in a Project and call mlapp.Execute("..."); I get the exception QueryInterface for interface MLapp.DIMLapp failed.
Why?
Laszlo Sragner
|
|
|
|
|
sragner wrote:
Is the sample available in C#?
No, you can write it...
sragner wrote:
when I add the Reference in a Project and call mlapp.Execute(".
? what do you mean ?
Jonathan de Halleux.
|
|
|
|
|
My filter is a sixth order bessel low pass filter.
Here is the matlab code.
function filter
clear all;
a=[10395];
wo=1/(23.43e6)
b=[1*(wo^6) 21*(wo^5) 210*(wo^4) 1260*(wo^3) 4725*(wo^2) 10395*(wo) 10395];
c=tf(a,b)
h=c2d(c,1/52.32e6,'tustin')
bode(h)
I wrote the same code in VC++
/*******************************************************************************************
Transfer function:
10395
---------------------------------------------------
6.045e-045 s^6 + 2.974e-036 s^5 + 6.968e-028 s^4
+ 9.796e-020 s^3 + 8.607e-012 s^2
+ 0.0004437 s + 10395
Transfer function:
0.02651 z^6 + 0.1591 z^5 + 0.3977 z^4 + 0.5302 z^3
+ 0.3977 z^2 + 0.1591 z + 0.02651
---------------------------------------------------
z^6 + 0.1852 z^5 + 0.4568 z^4 + 0.01633 z^3
+ 0.03876 z^2 - 0.0007527 z + 0.0003637
Sampling time: 1.9113e-008
********************************************************************************************/
unsigned char bessel(unsigned char x) // Function accessible only from this file
{
double b0=0.02651,b1=0.1591,b2=0.3977, b3=0.5302, b4=0.3977, b5=0.1591, b6=0.02651;
double a1= -0.1852, a2= -0.4568, a3= -0.01633, a4= -0.03876, a5= 0.0007527, a6= -0.0003637;
double temp_x1,temp_x2,temp_x3,temp_x4,temp_x5,temp_x6,temp_x7;
double temp_y1,temp_y2,temp_y3,temp_y4,temp_y5,temp_y6;
double y;
unsigned char y_unsigned;
double static xn_1,xn_2,xn_3,xn_4,xn_5,xn_6;
double static yn_1,yn_2,yn_3,yn_4,yn_5,yn_6;
temp_x1 = x * b0;
temp_x2 = xn_1* b1;
temp_x3 = xn_2 * b2;
temp_x4 = xn_3 * b3 ;
temp_x5 = xn_4 * b4;
temp_x6 = xn_5 * b5;
temp_x7 = xn_6 * b6;
temp_y1 = yn_1 * a1;
temp_y2 = yn_2* a2;
temp_y3 = yn_3 * a3;
temp_y4 = yn_4 * a4 ;
temp_y5 = yn_5 * a5;
temp_y6 = yn_6 * a6;
y = temp_x1 + temp_x2 + temp_x3 + temp_x4 + temp_x5 + temp_x6 + temp_x7 + temp_y1 + temp_y2 + temp_y3 + temp_y4 + temp_y5 + temp_y6 ;
xn_6 = xn_5;
xn_5 = xn_4;
xn_4 = xn_3;
xn_3 = xn_2;
xn_2 = xn_1;
xn_1 = (double) x;
yn_6 = yn_5;
yn_5 = yn_4;
yn_4 = yn_3;
yn_3 = yn_2;
yn_2 = yn_1;
yn_1 = y;
y_unsigned = (unsigned char) y;
return y_unsigned;
}
I am working with an experimental platform and filtering is one of the applications of it.
What i am looking for,is to get my matlab plot function when i run the code,after i have done suitable routine and created libraries( you are the specialist).
I hope i'am not too confusing.Please let me know if you need more explanation,or i can send you my code to check if you have some time.
From you name,i can deduce you might be a french speaker
Thx
F.K
|
|
|
|
|
flora_k wrote:
I wrote the same code in VC++
Where is it ?
flora_k wrote:
you might be a french speaker
Yes indeed.
Btw, you're bessel function looks strange to me: you are usingt a lot of uninitialized parameters;..
Jonathan de Halleux.
|
|
|
|
|
I put the code on the previous message. i just copy/paste it.
All the parameters have been initialized. i think it's a good idea i give you the insight of the whole thing. There we go
// CPPAnalyzerTestModule.cpp : Implementation of CPPAnalyzerTestModule
#include "stdafx.h"
#include "PPAnalyzerTestModule.h"
#include "CPPAnalyzerTestModule.h"
#include "StrDef.h"
// for filter function
#include <stdio.h>
#include <math.h>
//for matlab interfacing
#include <engine.h>
#include "myfunctions.h"
#define BUFSIZE 256
Engine*ep;
mxArray *A_ptr;
double *A;
/////////////////////////////////////////////////////////////////////////////
// CPPAnalyzerTestModule
// handlers used by this module
PPHANDLER_IMPLEMENT_USAGE(PPLogHandler)
PPHANDLER_IMPLEMENT_USAGE(PPErrorHandler)
// imported command id's from other module classes to use PPCMD() macros
#define IMPORT_MODULECOMMANDS
#include "PPChainLib\CmdMap.h"
#include "PPProxyLib\CmdMap.h"
/* TODO: Add #includes for other module classes used:
#include "PPSomeModule\CmdMap.h"
#include "PPOtherModule\CmdMap.h"
... or delete the entire IMPORT_MODULECOMMANDS section if not needed */
#undef IMPORT_MODULECOMMANDS
// function prototypes
void Filter(long amount, unsigned char* pData);
unsigned char bessel(unsigned char x);
// -------------------------------------------------------
// CONSTRUCTOR/DESTRUCTOR
//##ModelId=3B6171AE006E
CPPAnalyzerTestModule::CPPAnalyzerTestModule()
{
PPHANDLER_START_USAGE(PPLogHandler)
PPHANDLER_START_USAGE(PPErrorHandler)
PPLOG2(COARSE, CHAINMODULES, INF, STR_STARTUP, GetModuleClassName())
InitMatlab();
}
//##ModelId=3B6171AE006F
CPPAnalyzerTestModule::~CPPAnalyzerTestModule()
{
PPLOG2(COARSE, CHAINMODULES, INF, STR_SHUTDOWN, GetModuleClassName())
PPHANDLER_STOP_USAGE(PPErrorHandler)
PPHANDLER_STOP_USAGE(PPLogHandler)
CloseMatlab();
}
// -------------------------------------------------------
// PUBLIC COM INTERFACE METHODS
STDMETHODIMP CPPAnalyzerTestModule::Reset(int *result)
{
// keep functionality of baseclass
return CPPChainModuleBase::Reset(result);
}
//##ModelId=3B6171AE007A
STDMETHODIMP CPPAnalyzerTestModule::SetChainModuleId(long idModule, int *result)
{
// keep functionality of baseclass
return CPPChainModuleBase::SetChainModuleId(idModule, result);
}
//##ModelId=3B6171AE007E
STDMETHODIMP CPPAnalyzerTestModule::Connect(unsigned inputNr, IPPChainModule* pPrevModule, unsigned prevOutputNr, int *result)
{
// keep functionality of baseclass
return CPPChainModuleBase::Connect(inputNr, pPrevModule, prevOutputNr, result);
}
//##ModelId=3B6171AE008C
STDMETHODIMP CPPAnalyzerTestModule::SetParameter(IUnknown* pIUnk, int* result)
{
// extend functionality of baseclass
// following file implements the moduleparameter dispatch switch
#include "ParMap.h"
}
//##ModelId=3B6171AE0091
STDMETHODIMP CPPAnalyzerTestModule::SetCommand(long idDest, long idCmd, __int64 offset, const unsigned char* pData, long amount, int* result)
{
// keep functionality of baseclass
return CPPChainModuleBase::SetCommand(idDest, idCmd, offset, pData, amount, result);
}
//##ModelId=3C6D24A501D3
STDMETHODIMP CPPAnalyzerTestModule::IsEnabled(int *IsEnabled, int *ModuleName, int *result)
{
// keep functionality of baseclass
return CPPChainModuleBase::IsEnabled(IsEnabled, ModuleName, result);
}
//##ModelId=3B6171AE009F
STDMETHODIMP CPPAnalyzerTestModule::Validate(int* result)
{
// extend functionality of base class
*result = PP_OK;
HRESULT hr = CPPChainModuleBase::Validate(result);
if (SUCCEEDED(hr) && (*result == PP_OK))
{
// TODO: Add code here for further validation
}
return hr;
}
//##ModelId=3B6171AE00A9
STDMETHODIMP CPPAnalyzerTestModule::Prepare(int* result)
{
// extend functionality of base class
*result = PP_OK;
HRESULT hr = CPPChainModuleBase::Prepare(result);
if (SUCCEEDED(hr) && (*result == PP_OK))
{
}
return hr;
}
//##ModelId=3B6171AE00AC
STDMETHODIMP CPPAnalyzerTestModule::Run(int* result)
{
// keep functionality of baseclass
return CPPChainModuleBase::Run(result);
}
//##ModelId=3C8F773300EF
STDMETHODIMP CPPAnalyzerTestModule::HandleEvent(eModuleEventType eventType, int * result)
{
// keep functionality of baseclass
return CPPChainModuleBase::HandleEvent(eventType, result);
}
//##ModelId=3B6171AE00AF
STDMETHODIMP CPPAnalyzerTestModule::Pull(unsigned outputNr, long amount, long *amountActual, unsigned char* pData, unsigned char * ppCmds, int *more, int *result)
{
HRESULT hr = S_OK;
// replace functionality of baseclass
PullEntry(outputNr, amount, amountActual, pData, ppCmds, more, result);
if (*result == PP_OK)
{
// the main thing: read from previous module
hr = PullPrevModule(0, amount, amountActual, pData, ppCmds, more, result);
if (SUCCEEDED(hr) && (*result == PP_OK))
{
// command preprocessing
PullTransposeCmds(ppCmds, amountActual, pData); // TODO: override if necessary
PullInsertCmds(ppCmds, amountActual, pData);
// a basic loop for command processing
CCmdIterator iter(ppCmds);
CCommand *pCmd;
while (!iter.Ready() && (*result == PP_OK) && *more)
{
if ((pCmd = iter.GetNextCmdForMe(GetChainModuleId())) != NULL)
{
HandleCommand(pCmd, amountActual, pData, more, result);
if (!pCmd->IsBroadcastCmd())
delete pCmd;
}
}
}
/*
Process the data in this block
*/
// call your function
// use number of samples (amount actual)
// use buffer :
// yourfunc(long samples, unsigned char* pData);
//DisplayMatlab(*amountActual, pData, 0);
//FilterInMatlab(*amountActual, pData);
//either
//Filter(*amountActual, pData);
DisplayMatlab(*amountActual, pData, 1);
/*
Process the data in this block
*/
}
PullExit(outputNr, amount, amountActual, pData, ppCmds, more, result);
return hr;
}
//##ModelId=3BB850280291
STDMETHODIMP CPPAnalyzerTestModule::GetRunTimeInfo(const char* name, char* value, int maxlen, int* result)
{
// extend functionality of baseclass
// following file implements the runtimeinfo dispatch switch
#include "RtiMap.h"
}
STDMETHODIMP CPPAnalyzerTestModule::LogDumpRunTimeInfo(int* result)
{
// extend functionality of baseclass
// following lines implement the logdump of all runtimeinfo
#define LOGDUMP_MODULERUNTIMEINFO
#include "RtiMap.h"
#undef LOGDUMP_MODULERUNTIMEINFO
}
//##ModelId=3B61838B030A
STDMETHODIMP CPPAnalyzerTestModule::Abort(int* result)
{
// keep functionality of baseclass
return CPPChainModuleBase::Abort(result);
}
// -------------------------------------------------------
// OVERRIDEABLE METHODS
//##ModelId=3B6171AE0070
const char *CPPAnalyzerTestModule::GetModuleClassName() const
{
// override functionality of baseclass
return STR_MODULECLASSNAME;
}
//##ModelId=3BF1480F01AA
void CPPAnalyzerTestModule::HandleCommand(CCommand *pCmd, long *amountActual, unsigned char *pData, int* more, int *result)
{
// extend functionality of baseclass
// following file implements the commandhandler dispatch switch
#include "CmdMap.h"
}
// -------------------------------------------------------
// MODULEPARAMETER METHODS
// TODO: replace with your own module parameters
//##ModelId=3B6171AE00C9
int CPPAnalyzerTestModule::SetExampleParam(long value)
{
if (value < 0) // is just an example
{
PPERROR2(STR_ERR_EXAMPLEPARAM, GetModuleClassName())
PPLOG2(COARSE, CHAINMODULES, ERR, STR_ERR_EXAMPLEPARAM, GetModuleClassName())
return PP_NOT_OK;
}
m_ExampleParam = value;
return PP_OK;
}
// -------------------------------------------------------
// MODULERUNTIMEINFO METHODS
// TODO: replace with your own module runtime info
//##ModelId=3BF1480F00DF
int CPPAnalyzerTestModule::GetExampleInfo(char* value, int maxlen) const
{
// return example info
static long exampleInfo = 0;
_snprintf(value, maxlen, "ExampleInfo: %ld", exampleInfo++); // is just an example
return PP_OK;
}
// -------------------------------------------------------
// MODULECOMMAND METHODS
// TODO: replace with your own module commands
//##ModelId=3BF1480F01D9
int CPPAnalyzerTestModule::HandleSetByteExample(CCommand *pCmd, long *amountActual, unsigned char *pData, int* more)
{
// set byte to 0xee on offset location
pData[pCmd->GetOffset()] = 0xee; // is just an example
return PP_OK;
}
/*******************************************************************************************
Transfer function:
10395
---------------------------------------------------
6.045e-045 s^6 + 2.974e-036 s^5 + 6.968e-028 s^4
+ 9.796e-020 s^3 + 8.607e-012 s^2
+ 0.0004437 s + 10395
Transfer function:
0.02651 z^6 + 0.1591 z^5 + 0.3977 z^4 + 0.5302 z^3
+ 0.3977 z^2 + 0.1591 z + 0.02651
---------------------------------------------------
z^6 + 0.1852 z^5 + 0.4568 z^4 + 0.01633 z^3
+ 0.03876 z^2 - 0.0007527 z + 0.0003637
Sampling time: 1.9113e-008
********************************************************************************************/
unsigned char bessel(unsigned char x) // Function accessible only from this file
{
double b0=0.02651,b1=0.1591,b2=0.3977, b3=0.5302, b4=0.3977, b5=0.1591, b6=0.02651;
double a1= -0.1852, a2= -0.4568, a3= -0.01633, a4= -0.03876, a5= 0.0007527, a6= -0.0003637;
double temp_x1,temp_x2,temp_x3,temp_x4,temp_x5,temp_x6,temp_x7;
double temp_y1,temp_y2,temp_y3,temp_y4,temp_y5,temp_y6;
double y;
unsigned char y_unsigned;
double static xn_1,xn_2,xn_3,xn_4,xn_5,xn_6;
double static yn_1,yn_2,yn_3,yn_4,yn_5,yn_6;
temp_x1 = x * b0;
temp_x2 = xn_1* b1;
temp_x3 = xn_2 * b2;
temp_x4 = xn_3 * b3 ;
temp_x5 = xn_4 * b4;
temp_x6 = xn_5 * b5;
temp_x7 = xn_6 * b6;
temp_y1 = yn_1 * a1;
temp_y2 = yn_2* a2;
temp_y3 = yn_3 * a3;
temp_y4 = yn_4 * a4 ;
temp_y5 = yn_5 * a5;
temp_y6 = yn_6 * a6;
y = temp_x1 + temp_x2 + temp_x3 + temp_x4 + temp_x5 + temp_x6 + temp_x7 + temp_y1 + temp_y2 + temp_y3 + temp_y4 + temp_y5 + temp_y6 ;
xn_6 = xn_5;
xn_5 = xn_4;
xn_4 = xn_3;
xn_3 = xn_2;
xn_2 = xn_1;
xn_1 = (double) x;
yn_6 = yn_5;
yn_5 = yn_4;
yn_4 = yn_3;
yn_3 = yn_2;
yn_2 = yn_1;
yn_1 = y;
y_unsigned = (unsigned char) y;
return y_unsigned;
}
void Filter (long amount, unsigned char* pData)
{
long n;
unsigned char y;
for (n=0; n
|
|
|
|
|
What is your question / problem ?
Jonathan de Halleux.
|
|
|
|
|
Hello,
Here is my problem; i have a working program in matlab,say a filter. I have a ready made program in VC++ .What i want to do is to call and display my matlab filter in the VC++ code without actually opening a matlab window.
Is this possible with you theory?
I tried the source code, but there seems to be a problem, i keep having errors.
Help please
F.K
|
|
|
|
|
flora_k wrote:
What i want to do is to call and display my matlab filter in the VC++ code without actually opening a matlab window.
What do you mean exactly ?
flora_k wrote:
I tried the source code, but there seems to be a problem, i keep having errors.
If you don't give more details, I can't do much. Moreover, I've unsinstalled matlab so I won't be of any help.
Jonathan de Halleux.
|
|
|
|
|
Hello,
For the sample program to be provided, could you please indicate which header files and libraries( and their path as well) have to be included in order for the program to be compiled properly?
F.K
|
|
|
|
|
The files provided in the "source file" zip.
Jonathan de Halleux.
|
|
|
|
|
Hi again,
My question may sound silly,i am new in this. What is the relation ship between your theory and the matlab engine? What i mean is i can not see the C engine routine in your code.
Could you please provide sample of working code with your approach of the problem?
Thx
F.K
|
|
|
|
|
There is no C engine with my appraoch, the code is in C++.
I'm using the matlab engine through it's COM interface, without using the mx functions.
I cannot give a working example, check the demo.
Jonathan de Halleux.
|
|
|
|
|
Hi,
I am a beginner in this. I know a little about Matlab and not much about VC++.
I would like to call matlab functions from C.
Can somebody give me the exat syntax of mxCreateCharArray?
I mean like an example with specific values of argument ndim and const int *dims.
#include "matrix.h"
mxArray *mxCreateCharArray(int ndim, const int *dims);
The same for mxCreateDoublematrix,mxCreateString etc...
Thx
F.K
|
|
|
|
|
I designed this ActiveX module to avoid mx functions... Sorry can't help on that.
Jonathan de Halleux.
|
|
|
|
|
|
Hi,
Thanks for this nice code . I enjoy workng with it. I have a problem with getstring. In documentation you told that GetString allocate memory for the returned value and the user hould take care of clearing the memory. I look at the demo code. it seems there isn't such code in the sample. As i wrong ?
regards
|
|
|
|
|
mansour_ahmadian wrote:
In documentation you told that GetString allocate memory for the returned value and the user hould take care of clearing the memory. I look at the demo code. it seems there isn't such code in the sample. As i wrong
If you look deeper at the end of GetString you see
{
_bstr_t s(m_vResult);
szString=new TCHAR[s.length()+1];
_tcscpy( szString, (LPCTSTR)s);
}
That's where the copy arises...
Jonathan de Halleux.
|
|
|
|
|
i posted this in the visual c++ forum:
hello @all,
i need an instruction which waits until MATLAB will finish it's job.
earlier forum question:
hello @all,
i try to explain what i want / must do :
i have something like this:
<br />
i=0;<br />
while(i<5)<br />
{<br />
i++;<br />
}<br />
the only problem is the while loop. without these, the program part runs perfectly. however i need a while loop or something like that.
i think, the problem lie in the fact that the program sends the data to matlab and then directly in the code continues to go. possibly different processes run off parallel.
i think i must have something that waits so long, till matlab is ready with the diagram (i tried Sleep(1000) but it do not work).
maybe somebody know, if matlab has got a 'instruction' or if i can make something like a 'queue'.
thank you very much
sunny
i hope you can help me......
sunny
|
|
|
|
|
i m new in this forum. i found this MATLAB wrapper very nice, and helpful for fast debugging and other problems i faced in my master.
well, i guess u can use a barrier, for example let matlab write a file on disk and in the C++ part u may loop untill u find this file. it is a naive idea , but i m not yet experienced in COM
|
|
|
|
|
I have been uisng the Matlab engine DLL interface.
Why is it better to use the ActiveX interface?
Are ther any new APIs.
Yosi
|
|
|
|
|