Hi Smalltalkers,
I'm trying to use Dolphin's COM interface to communicate with MATLAB. The MATLAB Visual Basic examples look so simple, I though it was a piece of cake but it turned out not to be not so easy. As far as I can see I have two problems; A - I need to pass an empty SafeArray. In Visual Basic this is "Dim A() As Double" but in Dolphin? The closed I could get after some trail and error is "SAFEARRAY length: -1 elementClass: elementClass: DOUBLE" (length: 0 isn't regarded as empty). To make this work I needed to modify SAFEARRAY>>copy to handle this empty array. It seems to work for copying data from Dolphin to MATLAB but I'm not sure about it. B - In the VB example the client code creates the array, passes it to MATLAB which fills it with data. On inspection the result only contains zero's. I suspect I should add an indirection (pointer) because now it looks like the whole SAFEARRAY is copied by Dolphin before passing to MATLAB so MATLAB writes in a copy of the array which I never get to see again. Is this correct? If so how do I do this? Thanks, Pieter Emmelot The VB example to copy a matrix to a SAFEARRAY looks like this: Option Base 1 Dim MatLab As Object Dim MReal(2, 4) As Double Dim MImag() As Double Set MatLab = CreateObject("Matlab.Application") MatLab.Execute("a = [1 2 3 4; 5 6 7 8;]") Call MatLab.GetFullMatrix("a", "base", MReal, MImag) The workspace code: matlab Execute: 'a = [1 2 3 4; 5 6 7 8;]'. pr := SAFEARRAY dimensions: #(2 4) elementClass: DOUBLE. pi := SAFEARRAY length: -1 elementClass: elementClass: DOUBLE. matlab GetFullMatrix: 'a' Workspace: 'base' pr: pr pi: pi pr elementAt: #(1 1) "Display it" The IDL: void GetFullMatrix( [in] BSTR Name, [in] BSTR Workspace, [in, out] SAFEARRAY(double)* pr, [in, out] SAFEARRAY(double)* pi); SAFEARRAY>>dimensions: anArray elementClass: elementClass "Answer a multi dimensional safe array with elements of type elementClass. The instance regards itself as the owner of the underlying safe array and will free it on receipt of a #free message, or upon finalization, unless previously sent a #detach message. For example: a := SAFEARRAY dimensions: #(2 3) elementClass: DOUBLE is compatible with the Visual Basic declaration: Option Base 1 Dim a(2, 3) As Double " | answer dimensions rgsabound | dimensions := anArray size. rgsabound := StructureArray length: dimensions elementClass: SAFEARRAYBOUND . 1 to: dimensions do: [:i | rgsabound at: i put: (SAFEARRAYBOUND new cElements: (anArray at: i); lLbound: 1)]. answer := OLEAutLibrary default safeArrayCreateEx: elementClass vt cDims: dimensions rgsabound: rgsabound yourAddress pvExtra: nil. answer beFinalizable. ^answer |
Pieter
You wrote in message news:[hidden email]... > Hi Smalltalkers, > I'm trying to use Dolphin's COM interface to communicate with MATLAB. The > MATLAB Visual Basic examples look so simple, I though it was a piece of cake > but it turned out not to be not so easy. As far as I can see I have two > problems; > A - I need to pass an empty SafeArray. In Visual Basic this is "Dim A() > As Double" but in Dolphin? The closed I could get after some trail and error > is "SAFEARRAY length: -1 elementClass: elementClass: DOUBLE" (length: 0 > isn't regarded as empty). To make this work I needed to modify > SAFEARRAY>>copy to handle this empty array. It seems to work for copying > data from Dolphin to MATLAB but I'm not sure about it. No, that is not right. A length 0 SAFEARRAY is empty. A length of -1 is invalid. If you pass a length of -1 then the call to SafeArrayCreateVectorEx() API will fail, and you'll just end up with a null SAFEARRAY (i.e. the same thing as executing 'SAFEARRAY newPointer'). > B - In the VB example the client code creates the array, passes it to > MATLAB which fills it with data. On inspection the result only contains > zero's. I suspect I should add an indirection (pointer) because now it looks > like the whole SAFEARRAY is copied by Dolphin before passing to MATLAB so > MATLAB writes in a copy of the array which I never get to see again. Is this > correct? If so how do I do this? Make sure you are using interfaces generated from the typelib rather than IDispatch #doesNotUnderstand: processing. The latter passes all parameters wrapped as VARIANTs using a standard conversion to a VARIANT (#asVariant), which will not work correctly for an in-out SAFEARRAY. If you really must use IDispatch, then you will have to convert the SAFEARRAYs to VARIANTs yourself so that they point at the original arrays and have the VT_BYREF flagged OR'd into the 'vt' field. Regards Blair |
"Blair McGlashan" <[hidden email]> wrote in message
news:amvdhi$9f1fr$[hidden email]... | > B - In the VB example the client code creates the array, passes it to | > MATLAB which fills it with data. On inspection the result only contains | > zero's. I suspect I should add an indirection (pointer) because now it | looks | > like the whole SAFEARRAY is copied by Dolphin before passing to MATLAB so | > MATLAB writes in a copy of the array which I never get to see again. Is | this | > correct? If so how do I do this? | | Make sure you are using interfaces generated from the typelib rather than | IDispatch #doesNotUnderstand: processing. I get an "Interface not registered" error when doing "matlab := IMLApp new". Registering MLApp.tlb (see below) doesn't help. Since the VB code works I continued with IDispatch. | The latter passes all parameters | wrapped as VARIANTs using a standard conversion to a VARIANT (#asVariant), | which will not work correctly for an in-out SAFEARRAY. If you really must | use IDispatch, then you will have to convert the SAFEARRAYs to VARIANTs | yourself so that they point at the original arrays and have the VT_BYREF | flagged OR'd into the 'vt' field. Ok, I created a subclass of SAFEARRAY called MLSAFEARRAY and redefined #asVariant as: ^VARIANT new vt: self vt; ulVal: self asParameter; beByRef; "set VT_BYREF" yourself Then I instantiated a MLSAFEARRAY o := MLSAFEARRAY length: 1 elementClass: DOUBLE o class == SAFEARRAY "true" and got a SAFEARRAY object back! I looks like the VM is wrapping safe array COM objects in instances of SAFEARRAY class. For example o := OLEAutLibrary default safeArrayCreateVectorEx: 5 lLbound: 1 cElements: 1 pvExtra: nil o class == SAFEARRAY "true" Does the VM automagically creates SAFEARRAY instances from pointers to SafeArray COM objects? Regards, Pieter |
Pieter
You wrote in message news:[hidden email]... > ... > I looks like the VM is wrapping safe array COM objects in instances of > SAFEARRAY class. For example > o := OLEAutLibrary default safeArrayCreateVectorEx: 5 lLbound: 1 > cElements: 1 pvExtra: nil > > o class == SAFEARRAY "true" > > Does the VM automagically creates SAFEARRAY instances from pointers to > SafeArray COM objects? > The VM is unaware of the SAFEARRAY class. The reason a SAFEARRAY instance is required is because that is the way the external library call is declared (see the return type of OLEAutLibrary>>safeArrayCreateVectorEx:). Regards Blair |
"Blair McGlashan" <[hidden email]> wrote in message
news:an25au$af6sp$[hidden email]... | Pieter | | You wrote in message news:[hidden email]... | > ... | > I looks like the VM is wrapping safe array COM objects in instances of | > SAFEARRAY class. For example | > o := OLEAutLibrary default safeArrayCreateVectorEx: 5 lLbound: 1 | > cElements: 1 pvExtra: nil | > | > o class == SAFEARRAY "true" | > | > Does the VM automagically creates SAFEARRAY instances from pointers to | > SafeArray COM objects? | > | | The VM is unaware of the SAFEARRAY class. The reason a SAFEARRAY instance is | required is because that is the way the external library call is declared | (see the return type of OLEAutLibrary>>safeArrayCreateVectorEx:). Ahhh, I get the picture, very nice! Thanks, Pieter |
Free forum by Nabble | Edit this page |