Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ ATL
Dear Friends!
I have problem while working with ATL(VS2008, C++).
I must use SAFEARRAY(IMyObject*)* parameters in idl file.
If SAFEARRAY(double)*, then use the CComSafeArray..., but for interfaces or my structures, I don't know how to solve.
Thank you in advanced.
 
The idl file is...
 
...
 
interface IMyObj2;
...
 
typedef struct SMyObj2{
    IMyObj2 * iobject;
}SMyObj2;
 
...
 
//.IMyObj2
[
	object,
	uuid(3454B81A-65A9-4F3E-8678-1D5F82B25837),
	oleautomation,
	nonextensible,
	helpstring("IMyObj2 Interface"),
	pointer_default(unique)
]
interface IMyObj2 : IUnknown{
	[propget, helpstring("property ID")] 
	HRESULT ID([out, retval] LONG* pVal);
	[propput, helpstring("property ID")] 
	HRESULT ID([in] LONG newVal);
};
 
...
 

[
	object,
	uuid(EF532C8B-12A9-4FEC-B91C-D7502FD68874),
	oleautomation,
	nonextensible,
	helpstring("IArrayMan3 Interface"),
	pointer_default(unique)
]
 
interface IArrayMan3 : IUnknown{
	[helpstring("method GetArray")] 
	HRESULT _stdcall GetArray2(SAFEARRAY(SMyObj2)* pArray);
	[helpstring("method PutArray")] 
	HRESULT _stdcall PutArray2(SAFEARRAY(SMyObj2) pArray);
};
 
C++ file...
STDMETHOD(GetArray2)(SAFEARRAY** pArray)
{
	CComSafeArray<IUnknown*> ppp;//.Compile Okay.
//	CComSafeArray<SMyObj2, VT_VARIANT> arr;//.Compile Error
//      CComSafeArray<IMyObj2*> ttt;//.Compile Error
	return S_OK;
}
Posted 18-Sep-12 22:06pm

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Greetings!
First of all it is nessesary to get an info from type library using IRecordInfo interface:
GUID GUID_SMyObj2 = __uuidof(SMyObj2);
HRESULT hr;
CComPtr<IRecordInfo> srecnfo;
hr = GetRecordInfoFromGuids(LIBID_MyLib /*here is your type lib identifier*/, 1, 0, 0, GUID_SMyObj2, &srecnfo);
if(FAILED(hr))
  _com_issue_errorex(hr, NULL, IID_NULL);
If this part will be successful, then it is possible to create a safearray or custom type:
const LONG l_bound = 0, u_bound = 2;
LPSAFEARRAY lpSMyObj2 = SafeArrayCreateVectorEx(VT_RECORD, l_bound,
  u_bound - l_bound + 1, srecnfo);
if(!lpSMyObj2)
  _com_issue_errorex(E_FAIL, NULL, IID_NULL);
or access and use existing:
//LPSAFEARRAY lpSMyObj2 got from somewhere
//getting bounds of array
  LONG l_bound = 0, u_bound = 0;
  HRESULT hr1 = SafeArrayGetLBound(lpSMyObj2, 1, &l_bound);
  HRESULT hr2 = SafeArrayGetUBound(lpSMyObj2, 1, &u_bound);
  if(FAILED(hr1) || FAILED(hr2) )
  {
      // handle an error
  }
  else
  { 
     ...
     SMyObj2 * pSMyObj2 = NULL;
     HRESULT hr = SafeArrayAccessData(lpSMyObj2, (void**)&pSMyObj2);
     if(FAILED(hr))
       _com_issue_errorex(hr, NULL, IID_NULL);
     ...
  }
  // modifying data if needed
  for(int i = l_bound; i <= u_bound - l_bound; i++)
  {
    // do something with pSMyObj2[i].iobject
  }
  ...
  // Releasing an array
  hr = SafeArrayUnaccessData(lpSMyObj2);
  if(FAILED(hr))
    _com_issue_errorex(hr, NULL, IID_NULL);
Please see http://msdn.microsoft.com/en-us/library/aa148975.aspx[^] for more details
  Permalink  
v2
Comments
Mem 9021960 at 19-Sep-12 6:05am
   
Very thanks!
But Isn't there the method using template class such that CComSafeArray?
And if client program need the SAFEARRAY(IMyObj*)* parameters, is there any problems?
skydger at 19-Sep-12 7:05am
   
As far as I know, CComSafeArray uses VARIANT subsets of data, but not user defined. Besides it is a template wrapper class of SAFEARRAY and could not be flexible enogh for all the cases. So I think that using it with user defined types is little bit tricky. But maybe there is a solution to do so.
 
As for your question about using SAFEARRAY(IMyObj*)* instead of structure: it is the same as described, and it is simplier, because you need to create instances only (CoCreateInstance(...)) and release them.
Mem 9021960 at 19-Sep-12 7:22am
   
Dear Mr.skydger! I see.
As you see, I'm beginner at COM technology.
Thank you for your kindly help.
I often want your many help.
skydger at 19-Sep-12 8:00am
   
Sure, if it will be possible for me :)
I don't know, what is the structure of that interface (IMyObj2), but sometimes it is more convenient for me to create custom array interface (for example IMyObj2Collection) but not the safearray. If I need not just array of custom types, but something like map<,>.
Mem 9021960 at 19-Sep-12 20:29pm
   
Of course, I made the three array structure, it is IMyObj2**, IMyObj2Collection*, SAFEARRAY(IMyObj2*)*.
The two methods using IMyObj2** and IMyObj2Collection was completed already.
But required items has SAFEARRAY(IMyObj2*)*.
IMyObj2's structure is simple.
For example, Point structure(double x, double y,...).
And if client program is coded by C#, What happens?
skydger at 20-Sep-12 15:15pm
   
It is as implementation of classes in C#.
Please see the following article:
http://msdn.microsoft.com/ru-ru/library/c3fd4a20.aspx

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 CPallini 365
1 Sergey Alexandrovich Kryukov 262
2 OriginalGriff 165
3 George Jonsson 159
4 Richard MacCutchan 110
0 OriginalGriff 6,344
1 Sergey Alexandrovich Kryukov 5,860
2 CPallini 5,135
3 George Jonsson 3,559
4 Gihan Liyanage 2,522


Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 19 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100