I've found myself using this code often:
// Get the transient geometry object. We'll use this to create pure geometry CComPtr<TransientGeometry> pTrGeom; pTrGeom = pApp->TransientGeometry;
But I was thinking, once I have pTrGeom can I just declare a global to hold it while my Inventor instance is running?
Alternatively I suppose I could have a global function which does this:
CComPtr<TransientGeometry> GetTransientGeometryPtr() { static CComPtr<TransientGeometry> pTrGeom = NULL ;
if (pTrGeom == NULL) pTrGeom = pApp->TransientGeometry; return (pTrGeom) ; }
So it reduces to a one-liner. But in COM is that static valid? I know the code is not complete above, but you get the idea.
What do other C++ COM programmers do here...?
Solved! Go to Solution.
Solved by xiaodong_liang. Go to Solution.
Hi,
Both are fine to me. I perfer to defining it as global directly. It would look more clear.
Could you give me an example of how you do that?
Because when I do it I get an exception when I exit from my program.
It seems as if it is not being released properly or maybe released twice, but I'm not COM expert enough to understand the error.
Here is the code, I'm new to COM so there may be a supid error in here:
#include "stdafx.h" HRESULT ConnectToInventor (CComPtr<Application>& pInvApp) { CLSID InvAppClsid; HRESULT hRes = CLSIDFromProgID (L"Inventor.Application", &InvAppClsid); if (FAILED(hRes)) { pInvApp = nullptr ; return hRes ; } // See if Inventor is already running... CComPtr<IUnknown> pInvAppUnk; hRes = ::GetActiveObject (InvAppClsid, NULL, &pInvAppUnk); if (FAILED (hRes)) { // Inventor is not already running, so try to start it... wprintf (L"Could not get hold of an active Inventor , will start a new session\n") ; hRes = CoCreateInstance (InvAppClsid, NULL, CLSCTX_LOCAL_SERVER, __uuidof(IUnknown), (void **) &pInvAppUnk); if (FAILED (hRes)){ pInvApp = nullptr ; return hRes ; } } // Get the pointer to the Inventor application... hRes = pInvAppUnk->QueryInterface (__uuidof(Application), (void **) &pInvApp); if (FAILED(hRes)) { return hRes ; } return hRes ; } CComPtr<TransientGeometry> pTransGeom = nullptr ; void InitTransGeomPtr(CComPtr<Application>& pInvApp) { HRESULT hRes = pInvApp->get_TransientGeometry(&pTransGeom); } CComPtr<TransientGeometry> GetTransGeomPtr () { if (pTransGeom == nullptr) { wprintf (L"You have not called InitTransGeomPtr\n") ; } return (pTransGeom) ; } static void DoInventorTest () { CComPtr<Application> pInvApp ; HRESULT hRes = ConnectToInventor (pInvApp) ; if (FAILED(hRes)) { wprintf (L"*** Failed to connect to Inventor application ***\n"); return ; } InitTransGeomPtr (pInvApp) ; wprintf (L"Hit a key") ; _getwch() ; } int _tmain(int argc, _TCHAR* argv[]) { HRESULT Result = CoInitialize (NULL); if (SUCCEEDED(Result)) DoInventorTest(); CoUninitialize(); return 0; }
When I exit from the program I get the exception shown in the attacched screenshot.
All I want to do is be able to have a single transient geometry object/pointer which I init at the start and use throughout the program.
Maybe I'm missing a Release or delete or....
Hi,
I think it would be a good idea to release the pointer before calling CoUninitialize() - i.e. release the pTransGeom pointer at the end of DoInventorTest(), otherwise the release is only called implicitly when _tmain is returning since the variable is declared globally.
Cheers,
I thought it could be a "ignorance of com" problem. But how do you release the pointer? the compiler says it is a private function:
InvSupp.cpp(320): error C2248: 'ATL::_NoAddRefReleaseOnCComPtr<T>::Release' : cannot access private member declared in class 'ATL::_NoAddRefReleaseOnCComPtr<T>'
Hi,
It should work: http://stackoverflow.com/questions/4284621/some-questions-about-using-ccomptr-when-use-release-can-i...
Also worth pointing out this other thread: http://stackoverflow.com/questions/10179884/do-i-have-to-call-release-method-on-ccomptr-objects
Cheers,