1

Topic: SAFEARRAY as means of reset of an array

Kind time of days, dear colleagues! I made COM In-Process the server (in the form of DLL). This piece on a C ++ does some computing operation, and the array of results should return to head application. I would like to use SAFEARRAY - as means of reset of an array. For this purpose, a method (or property "get") should have [out] type parameter: [propget, id (7)] HRESULT Array1 ([out, retval] SAFEARRAY ** pVal); Here recommendations: https://msdn.microsoft.com/en-us/magazine/mt795188.aspx the Method of filling of an array should look approximately so: STDMETHODIMP CMyComComponent:: DoSomething (/* [out] */SAFEARRAY ** ppsa) noexcept {try {//Create a safe array storing ' count ' BYTEs const LONG count =/* some count value */; CComSafeArray <BYTE> sa (count);//Fill the safe array with some data for (LONG i = 0; i <count; i ++) {sa [i] =/* some value */;}//Return ("move") the safe array to the caller//as an output parameter *ppsa = sa. Detach ();} catch (const CAtlException& e) {//Convert ATL exceptions to HRESULTs return e;}//All right return S_OK;} Problem - that MIDL the compiler all time swears, on attempt of compilation of the above-stated property propget, id (7)] HRESULT Array1...: AlexGinTest1.idl (25): error MIDL2139: type of the parameter cannot derive from void or void *: [Type ' PVOID ' (Parameter ' pVal ')] AlexGinTest1.idl (25): error MIDL2105: pointee / array does not derive any size: [Field ' rgsabound ' of Struct ' tagSAFEARRAY ' (Parameter ' pVal ')] Viewed references on materials on application SAFEARRAY: https://blogs.msmvps.com/gdicanio/2011/ … msafearray https://www.codeproject.com/Articles/24 … DLL-Server But to understand how to solve the given problem while it is impossible. What thoughts about it are? P.S. Attempts to make provision of an array by the client, with filling on the server (and the further usage-clearing on the client), and access methods on type: [id (7)] HRESULT SetSafeArray ([in] SAFEARRAY (byte) ** ptrArr); [id (8)] HRESULT GetSafeArray ([out] SAFEARRAY (byte) ** ptrOutArr); Transit through MIDL the compiler, but are cut off by C errors ++ compilations: Error C2259 ' ATL:: CComObject <T> ': cannot instantiate abstract class AlexGinTest1 c:\program files (x86) \microsoft visual studio 14.0\vc\atlmfc\include\atlcom.h 2000

2

Re: SAFEARRAY as means of reset of an array

Hello, AlexGin, you wrote: AG> Attempts to make provision of an array by the client, with filling on the server (and the further usage-clearing on the client), and access methods on type:  odl/.idl SAFEARRAY already implies one indirection, thus for Set it is enough of it, for Get it is necessary two to select on client side [id (7)] HRESULT SetSafeArray ([in] SAFEARRAY (byte) ptrArr); [id (8)] HRESULT GetSafeArray ([out] SAFEARRAY (byte) * ptrOutArr); Thus in With ++: STDMETHODIMP CMyComComponent:: SetSafeArray (/* [in] */SAFEARRAY* ppsa) {...}//does not take away possession STDMETHODIMP CMyComComponent:: GetSafeArray (/* [out] */SAFEARRAY ** ppsa) {...}//selects on the implementation side

3

Re: SAFEARRAY as means of reset of an array

I understood in what a problem!!! 1) first of all that it was easier to correct all codes, it is necessary to select interface type: Custom (instead of Dual) - then the interface of my component will be successor IUnknown (instead of IDispatch) that allows to simplify all codes of the project. In this case - our component all the same is able work with the server on basis.NET (C#) applications. 2) methods of operation with SAFEARRAY in a file *.idl look so:... [] HRESULT SetSafeArray1 ([in] SAFEARRAY (byte) inputArray); [] HRESULT SetSafeArray2 ([in] SAFEARRAY (double) inputArray); [] HRESULT GetSafeArray1 ([out] SAFEARRAY (byte) * ptrArray); [] HRESULT GetSafeArray2 ([out] SAFEARRAY (double) * ptrArray);... A C ++ files: In  *.h: class ATL_NO_VTABLE CAlexGinAGT2:... {... public: STDMETHOD (SetSafeArray1) (SAFEARRAY * inputArray); STDMETHOD (SetSafeArray2) (SAFEARRAY * inputArray); STDMETHOD (GetSafeArray1) (SAFEARRAY ** ptrArray); STDMETHOD (GetSafeArray2) (SAFEARRAY ** ptrArray);...}; B a file of the codes *.cpp: #include "atlsafe.h"//It is for CComSafeArray support... STDMETHODIMP CMyClass:: SetSafeArray1 (SAFEARRAY * inputArray) {//TODO: Add your implementation code here//see://https://stackoverflow.com/questions/12484109/how-to-iterate-through-safearray m_vectBytes.clear (); SAFEARRAY* saValues = inputArray; byte* pVals; HRESULT hr = SafeArrayAccessData (saValues, (void **) &pVals);//direct access to SA memory if (SUCCEEDED (hr)) {long lowerBound, upperBound;//get array bounds SafeArrayGetLBound (saValues, 1, &lowerBound); SafeArrayGetUBound (saValues, 1, &upperBound); long cnt_elements = upperBound - lowerBound + 1; for (int i = 0; i <cnt_elements; ++ i)//iterate through returned values {byte btVal = pVals [i]; m_vectBytes.push_back (btVal);} SafeArrayUnaccessData (saValues);}/* SafeArrayDestroy (saValues); */return S_OK;} STDMETHODIMP CMyClass:: SetSafeArray2 (SAFEARRAY * inputArray) {//TODO: Add your implementation code here m_vectDoubles.clear (); SAFEARRAY* saValues = inputArray; double* pVals; HRESULT hr = SafeArrayAccessData (saValues, (void **) &pVals);//direct access to SA memory if (SUCCEEDED (hr)) {long lowerBound, upperBound;//get array bounds SafeArrayGetLBound (saValues, 1, &lowerBound); SafeArrayGetUBound (saValues, 1, &upperBound); long cnt_elements = upperBound - lowerBound + 1; for (int i = 0; i <cnt_elements; ++ i)//iterate through returned values {double dbVal = pVals [i]; m_vectDoubles.push_back (dbVal);} SafeArrayUnaccessData (saValues);}/* SafeArrayDestroy (saValues); */return S_OK;} STDMETHODIMP CMyClass:: GetSafeArray1 (SAFEARRAY ** ptrArray) {//TODO: Add your implementation code here//see://https://msdn.microsoft.com/en-us/magazine/mt795188.aspx try {//Create a safe array storing ' count ' BYTEs const LONG count = m_vectBytes.size (); CComSafeArray <BYTE> sa (count);//Fill the safe array with some data for (LONG i = 0; i <count; i ++) {sa [i] = m_vectBytes [i];}//Return ("move") the safe array to the caller//as an output parameter *ptrArray = sa. Detach ();} catch (const CAtlException& e) {//Convert ATL exceptions to HRESULTs return e;} return S_OK;} STDMETHODIMP CMyClass:: GetSafeArray2 (SAFEARRAY ** ptrArray) {//TODO: Add your implementation code here try {//Create a safe array storing ' count ' BYTEs const LONG count = m_vectBytes.size (); CComSafeArray <DOUBLE> sa (count);//Fill the safe array with some data for (LONG i = 0; i <count; i ++) {sa [i] = m_vectDoubles [i];} //Return ("move") the safe array to the caller//as an output parameter *ptrArray = sa. Detach ();} catch (const CAtlException& e) {//Convert ATL exceptions to HRESULTs return e;} return S_OK;} the REMARK: Among the master (wizard) it is entered all methods of operation with SAFEARRAY (as in a combo-boxing of a choice of data types in a window of a method/property is not present SAFEARRAY it is entered manually) then it is required to correct three files specified above manually also. On the side.NET the client, to data type SAFEARRAY there corresponds type: System. Array.