Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Different method of accessing ATL COM

Posted on 2004-09-14
7
Medium Priority
?
289 Views
Last Modified: 2013-11-25
Hi,
If you want to use ATL COM in your client application ( VC++ ) Then you can use it through following 2 methods:
1. "Import 'path of dll' " 
2. "include .h and i.c files" right .

there is method with following signature in ATL COM.

GetUserName(out,retval BSTR )


In my client application code will look like this

BSTR bstrUserName= ptrToComServer->GetUserName();

I think till now everything is clear.

Problem is that If I use Import dll (method one) then I can use above line

in case of Include files( method 2 ) I can't use all those methods with above signature.

If my question is not clear pls do tell me so that I can provide some more details.

Can you tell me why I am unable to use [ out,retval ] in case of method 2.
0
Comment
Question by:nkaushik
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 9

Accepted Solution

by:
_ys_ earned 800 total points
ID: 12062245
> you can use it through following 2 methods:
There can be considered three, where the third is a hybrid of your two [... details towards the end ...]

> 2. "include .h and i.c files" right .
The actual method signature would have a return type of HRESULT:
HRESULT GetUserName([out,retval] BSTR*)

When using the header method this is all you have. You've oprted to do things the C++ way. You're expected to use this signature and process the HRESULT value - it is useful to know this value, especially upon failure.

> 1. "Import 'path of dll' " 
When you use #import it wraps this method:
inline _bstr_t IComServer::GetUserName ( ) {
    BSTR _result = 0;
    HRESULT _hr = raw_GetUserName(&_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _bstr_t(_result, false);
}

All this does is call onto the original signature [HRESULT _hr = raw_GetUserName(&_result);] and processes the HRESULT for you, throwing an exception if warranted.

In other words, it's trying to do things the way VB does it - become an automation client.

> 1. "Import 'path of dll' " 
Do things the automation client way - same as what VB does
> 2. "include .h and i.c files" right .
Do things the C++ way


The way I see it is, you have three choices:

1. use #import the way you currently are.
try {
    BSTR sUserName = pComServer->GetUserName ( );
    SysFreeString(sUserName);
}
catch (_com_error &ex) { ...
}

2. use the header files as you suggested.
HRESULT hr;
BSTR sUserName;
if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}
else { ...
}

3. use #import with the raw_interfaces_only attribute. [... this is the third way ...]
#import "path to type library" raw_interfaces_only
HRESULT hr;
BSTR sUserName;
if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}
else { ...
}
0
 

Author Comment

by:nkaushik
ID: 12062570
Hi YS,
       Thanks for your prompt reply it was really nice explanation did't take any time to understand.
My Problem is solved now and code is working fine.
So there is no difference in calling from client(VC++) when we use Method 2 for following 2 signatures

  1. GetUserName([in,out] bstrUserName)
  2. GetUserName([out,retval] bstrUserName)

Calling code for 1 and 2 signature will be:

   HRESULT hr;
  BSTR sUserName;
  if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
     SysFreeString(sUserName);
     }



So there is a difference in calling from client(VC++) when we use Method 1 for following 2 signatures

  1. GetUserName([in,out] bstrUserName)
  2. GetUserName([out,retval] bstrUserName)

  Calling code for signature 1 and 2 will be :
    1. Calling code will be same like above
     2. BSTR bstrUserName=pComServer->GetUserName()


 Keep it Up!!!!
 
   

0
 
LVL 9

Expert Comment

by:_ys_
ID: 12062656
> So there is no difference in calling from client(VC++) when we use Method 2 for following 2 signatures
>  1. GetUserName([in,out] bstrUserName)
>  2. GetUserName([out,retval] bstrUserName)

Sorry, but there is a difference here ... apart from the obvious signature ...

The difference is due to memory management. By specifying a BSTR parameter as [in] you're telling the COM server that memory has already been allocated.

1. GetUserName([in,out] bstrUserName)
HRESULT hr;
BSTR sUserName = SysAllocString(L""); // [in] is specified so we need to allocate memory
if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}

Note that the COM server uses SysReAllocString (or SysFreeString / SysAllocString) if neceessary.

2. GetUserName([out,retval] bstrUserName)
HRESULT hr;
BSTR sUserName; // no need to allocate memory as [in] not specified. Indeed soing so would cause a memory leak
if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}

Note that the COM server uses SysAllocString.

And just for completeness sake:
3. GetUserName([in] bstrUserName)
HRESULT hr;
BSTR sUserName = SysAllocString(L""); // [in] is specified so we need to allocate memory
if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}

Note that the COM server doesn't allocate or deallocate memory. In fact reallocation should not be performed either. The COM server should treat this as read-only.


In all scenarios, the COM client must invoke SysFreeString when complete, else a memory leak results.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:nkaushik
ID: 12062690
Your are right Mr. YS there is difference internally but what I meant is there is no difference in calling convention( means signature from client app).
0
 
LVL 9

Expert Comment

by:_ys_
ID: 12062901
That's right, both are invoked the same way.

if (SUCCEEDED(hr = pComServer->GetUserName (&sUserName))) {
    SysFreeString(sUserName);
}
0
 

Author Comment

by:nkaushik
ID: 12063108
by the way where are you from and on which technology or technologies you are working ??
0
 
LVL 9

Expert Comment

by:_ys_
ID: 12063369
I've updated my member profile with a few details for all to read.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Ready to get certified? Check out some courses that help you prepare for third-party exams.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question