• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1076
  • Last Modified:

Matlab and Automation and C++

Hi! I have got the following poerl code to execute data with Matlab.

# First create two SAFE_ARRAYs (Can only pass SAFE_ARRAY?)
my $MReal = Variant(VT_ARRAY|VT_R8, [1,2], 2);
my $MImag = Variant(VT_ARRAY|VT_R8, [1,2], 2);
# Set the values

# Put the matrix into MATLAB
$ML->PutFullMatrix('B', 'base', $MReal, $MImag);

I have tried to reproduce this code in C++:
VARIANTARG vargs[4];

CString command;


saPr[0].cElements = 10;
saPr[0].lLbound = 0;
vArrayPr = SafeArrayCreate(VT_R8 | VT_BYREF | VT_ARRAY, 1, saPr);

saPi[0].cElements = 0;
saPi[0].lLbound = 0;
vArrayPi = SafeArrayCreate(VT_R8 | VT_BYREF | VT_ARRAY, 0, saPi);

// initialize the variant args
VariantInit (&vargs[0]);
V_VT(&vargs[0]) = VT_BSTR;
V_BSTR(&vargs[0]) = command.AllocSysString();
VariantInit (&vargs[1]);
V_VT(&vargs[1]) = VT_BSTR;
V_BSTR(&vargs[1]) = L"base";

VariantInit (&vargs[2]);
V_VT(&vargs[2]) = VT_ARRAY | VT_R8 | VT_BYREF;
V_ARRAYREF(&vargs[2]) = &vArrayPr;

VariantInit (&vargs[3]);
V_VT(&vargs[3]) = VT_ARRAY | VT_R8 | VT_BYREF;
V_ARRAYREF(&vargs[3]) = &vArrayPi;

DispParams.cArgs = 4;
DispParams.rgvarg = vargs;
DispParams.cNamedArgs = 0;
DispParams.rgdispidNamedArgs = NULL;

// prepare for exceptions and initialize the return variante
memset (&ExcepInfo, sizeof (EXCEPINFO), '\0');
VariantInit (&vret);

// call Invoke
hr = m_lpDispatch->Invoke (m_DispGetFullMatrixID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&DispParams, &vret, &ExcepInfo, NULL);

But the C++ Invoke call returns: Type mismatch.

Can anybody help me?

Thanks in Advance

1 Solution
Howdy, Gus
    At first glance, it looks like you're almost there, except for one small thing--the order of the arguments inside DispParams.rgvarg above should be reversed.  No doubt Brockschmidt is better at explaining it than I (ref. Chapter 14 of Inside OLE, which is included in the online docs for MS VC++):

"The order of the arguments inside the rgvarg array is from last to first—that is, a right to left stacking order. Say, for example, that you invoke a method with three arguments as follows:

Object.Method(arg1, arg2, arg3)

You would then have the value 3 in pDispParams->cArgs, with arg1 at rgvarg[2], arg2 at rgvarg[1], and arg3 at rgvarg[0]."

I think this might be the answer, but I'd be able to tell for sure if you showed me the IDL for the PutFullMatrix function and/or the GetFullMatrix function--can't be 100% sure as is, since I'm not familiar with Perl (i.e., does it reverse the parameters in PutFullMatrix() for you like VB does)....  (By the way, which function are you trying to call--the Perl code shows PutFullMatrix, while the C++ looks like it's using the dispID for GetFullMatrix; this could be the problem as well, but I suspect it's just a typo....)  You can use the OLE/COM Object Viewer (under the tools menu in MS VC++ if you're not familiar with it) to look at the type library (written in IDL) for the Matlab Automation Server (the $ML object in the Perl code) in order to see the IDL code for the two functions; post it and I'll translate it to C++ for you.  Also, FYI, the parameter order is NOT reversed if you use MFC's InvokeHelper() instead of klunky ol' Invoke().... go figure!?

Hope this helps.  Let me know of any follow-up q's....

-Russ Fuller

Gus012498Author Commented:
Thank you very much for your answer. The problem to connect to Matlab from C++ is not already solved now, (I got another error message regarding the passed parameters) but Matlab does no longer respond with an Invalid_Type error.

Best regards


Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now