|
Hello Kishor,
Usage of CStrings in an exported function is perfectly fine as far as I know. Your function is declared as :
extern "C" DllExport const char* ActivatePlot(CString szPlot);
This means that when your ActivatePlot() is called, MFC creates a temporary CString for szPlot to be used within the context of the ActivatePlot() function.
Now, if this input is another CString as in the following example :
CString cstr("Country road.");
ActivatePlot(cstr);
the temporary CString "szPlot" which is created and gets passed into ActivatePlot() will contain a pointer to the same string that "cstr" points to.
The reference count of the actual string ("Country road.") is incremented and "cstr" and the "szPlot" both share the same string.
It is true that when the ActivatePlot() function exits, the CString destructor is called. This is done to free the temporary CString object "szPlot".
Let's take a look at the actual source codes of the CString destructor :
CString::~CString()
// free any attached data
{
if (GetData() != _afxDataNil)
{
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
FreeData(GetData());
}
}
What happens here is that the szPlot's string pointer's reference count is decremented and only if this reference count drops to zero (or negative) will the actual string be released.
In our example, if szPlot still points to the same string "Country road.", the reference count of this string in memory is decremented but the ref count will not be zero yet (cstr still holds a ref count) and no freeing is actually performed.
I believe no harm is actually done by the destructor in this sense.
Please provide more info on how you call the ActivatePlot() function as well what actually takes place in the function ActivatePlot() so that we can have a better picture of the nature of your crash.
Thanks,
Bio.
|
|
|
|
|
I desesperatly need help for passing a DISPPARAMS strucutre to IDispatch::Invoke.
Here is the calling code, in C++:
<br />
HRESULT hr;<br />
OLECHAR FAR* szMember = L"MyFunction";<br />
DISPID DispatchID;<br />
<br />
int i = 10;
<br />
DISPPARAMS DispatchParams;<br />
DispatchParams.cArgs=1;<br />
DispatchParams.rgvarg = new VARIANTARG[1];<br />
DispatchParams.rgvarg[0].vt = VT_BYREF|VT_INT;<br />
DispatchParams.rgvarg[0].pintVal = &i;<br />
DispatchParams.rgdispidNamedArgs=NULL;<br />
DispatchParams.cNamedArgs=0;<br />
<br />
CoInitialize(NULL);<br />
<br />
if (FAILED(hr = CoCreateInstance(MyCLSID, NULL, CLSCTX_SERVER, IID_IUnknown, (void FAR* FAR*)&pUnknown))) return hr;<br />
if (FAILED(hr = pUnknown->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pDispatch))) return hr;<br />
if (FAILED(hr = pDispatch->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_USER_DEFAULT, &DispatchID))) return hr;<br />
<br />
<br />
hr = pDispatch->Invoke(DispatchID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &DispatchParams, NULL, NULL, NULL);<br />
<br />
And this is the function I'm trying to call, in VB:
<br />
Public Function MyFunction(ByRef Parameter As Integer)<br />
MsgBox Str(Parameter), , "Parameter:"<br />
End Function<br />
When I run the calling code, IDispatch::Invoke returns a type mismatch error. However, if I enlarge the rgvarg field of the DispatchParams structure and write the parameter into rgvarg[1] instead of rgvarg[0] (while cArg is still 1), it does not return any error and MyFunction does show the message box, but it shows the value is 0, while it is supposed to be 10. I would add that I have no problems when using IDispatch::Invoke for calling functions that have no parameters.
I've spent hours trying to figure out what was wrong but it went nowhere. Would someone please help me ?
|
|
|
|
|
You have to use the VT_I2 or VT_I4 instead of VT_INT, because VT_INT is not OLE-compatible type at all.
Also the VB type "Integer" is the C/C++ type "short int". Therefore, you have to write
short int i = 10;
...<br />
DispatchParams.rgvarg[0].vt = VT_BYREF|VT_I2;<br />
DispatchParams.rgvarg[0].piVal = &i;
With best wishes,
Vita
|
|
|
|
|
Thank you so much, it helped a lot. Now I'm going to be careful with data types. However I have another question. I was wondering if it was possible to pass an array containing pointers to variables, these variables being either long integers or BSTR. I was thinking I could pass an array of variant, but I'm not sure about the result.
|
|
|
|
|
[quote]I was wondering if it was possible to pass an array containing pointers to variables, these variables being either long integers or BSTR. I was thinking I could pass an array of variant, but I'm not sure about the result. [/quote]
I think that this has no sense.
There is no array with reference data. Because the VARIANT with vt==VT_BYREF|VT_ARRAY|VT_?SIMPLETYPE? means the "pointer to SAFEARRAY with SIMPLETYPE members" (aka "SAFEARRAY(SIMPLETYPE)*") instead of the "SAFEARRAY with pointers to SIMPLETYPE data" (aka "SAFEARRAY(SIMPLETYPE*)").
Therefore, there is only SAFEARRAY(VARIANT) way, but the VB can use (or get) the VARIANT with VT_BYREF|VT_?SIMPLETYPE?, but cannot set such type. So I think that you can use only SAFEARRAY(VARIANT) with VT_?SIMPLETYPE? members.
With best wishes,
Vita
|
|
|
|
|
|
I want to find a LocalServer COM example not using ATL here. I have finished one but I don't know how to Register. I have tried it as below: mycom.exe -/RegServer
but my client can't create instance.so I think I have made mistaken on Registry.who can tell me something about registry?
|
|
|
|
|
i my project i search the /RegServer and /UnregServer in order to reg or unreg my server.
i do it like this in my CWinApp::InitInstance:
// ( _AtlModule is derived from CAtlMfcModule )
<br />
TCHAR szToken[] = _T("-/");<br />
long operation = 0;<br />
LPCTSTR lpsztoken = _AtlModule.FindOneOf( lpCmdline, szToken );<br />
<br />
while ( lpszToken != NULL )<br />
{<br />
if ( lstrcmpi( lpszToken, _T("RegServer") ) == 0 )<br />
{<br />
operation = 1;<br />
break;<br />
}<br />
if ( lstrcmpi( lpszToken, _T("UnregServer") ) == 0 )<br />
{<br />
operation = 2;<br />
break;<br />
}<br />
lpsztoken = _AtlModule.FindOneOf( lpCmdline, szToken );<br />
}<br />
<br />
switch ( operation )<br />
{<br />
case 0:
break:<br />
case 1:
_AtlModule.UpdateRegistryFromResource( MYUINT, TRUE );<br />
_AtlModule.RegisterServer( TRUE );<br />
break;<br />
case 2:
_AtlModule.UpdateRegistryFromResource( MYUINT, TRUE );<br />
_AtlModule.UnregisterServer( TRUE );<br />
break;<br />
}<br />
try like this ...
modified 14-Jun-22 21:01pm.
|
|
|
|
|
You have to use either
mycom.exe -RegServer
or
mycom.exe /RegServer
With best wishes,
Vita
|
|
|
|
|
Would this be safe? (the following code is implemented in a DLL, used by a single EXE and a bunch of COM DLLs)
CComAutoCriticalSection cs;
DWORD dwOwnerThreadId;
ISomeInterface* pObject = 0;
IStream* pObjMarshalled = 0;
HRESULT RegisterGlobalObject(ISomeInterface* pObj)
{
if(!cs.Lock())
return E_FAIL;
if(pObject != 0) {
cs.Unlock();
return E_UNEXPECTED;
}
HRESULT hr = CoMarshalInterThreadInterfaceInStream(
__uuidof(ISomeInterface),
pObj,
&pObjMarshalled
);
if(FAILED(hr)) {
cs.Unlock();
return hr;
}
pObject = pObj;
dwOwnerThreadId = GetCurrentThreadId();
cs.Unlock();
return S_OK;
}
HRESULT GetGlobalObject(ISomeInterface** ppObj)
{
if(!ppObj)
return E_POINTER;
if(!pObject)
return E_FAIL;
if(!cs.Lock())
return E_FAIL;
if(GetCurrentThreadId() == dwOwnerThreadId) {
*ppObj = pObject;
(*ppObject)->AddRef();
cs.Unlock();
return S_OK;
}
*ppObj = 0;
LARGE_INTEGER seek;
seek.QuadPart = 0;
HRESULT hr = pObjMarshalled->Seek(seek, STREAM_SEEK_SET, NULL);
if(FAILED(hr) {
cs.Unlock();
return hr;
}
hr = CoUnmarshalInterface(
pObjMarshalled,
__uuidof(ISomeInterface),
(void**)ppObj
);
cs.Unlock();
return hr;
}
I'm marshalling the interface pointer upon registration using the inter thread marshalling function, because I know that this function will not be called from any other process (it can't be). I also assume that CoUnmarshalInterface() will work for interfaces marshalled with CoMarshalInterThreadInterfaceInStream() .
I have yet to try this out (it's way past bedtime ). But if you read this and spot any inherent danger with this code, please let me know.
--
Sancte Míchael Archángele, defénde nos in proélio contra nequítiam et
insídias diáboli esto præsídium. Imperet illi Deus, súpplices deprecámur:
tuque, princeps milítiæ cæléstis, Sátanam aliósque spíritus malígnos, qui
ad perditiónem animárum pervagántur in mundo, divína virtúte,
In inférnum detrude. Amen.
|
|
|
|
|
Once the marshalled interface has been "picked up" from the stream and used, it seems that it's been used up already. I receive RPC_E_DISCONNECTED on method access.
I decided to make a singleton COM object which stores the ISomeInterface pointer instead. Then COM will handle everything automatically.
--
Sancte Míchael Archángele, defénde nos in proélio contra nequítiam et
insídias diáboli esto præsídium. Imperet illi Deus, súpplices deprecámur:
tuque, princeps milítiæ cæléstis, Sátanam aliósque spíritus malígnos, qui
ad perditiónem animárum pervagántur in mundo, divína virtúte,
In inférnum detrude. Amen.
|
|
|
|
|
You might have look to the IGlobalInterfaceTable . This allows multiple unmarshalling of once marshalled interface - if it helps you somehow.
|
|
|
|
|
Hello there,
Does anyone know how I can search for all registered COM objects that expose some specific (defined by me) interface?
|
|
|
|
|
hi frnd
One can search a component installed on a particular machine based on the CATID i.e category ID in which it falls.
there are two interfaces
ICatInformation using methods of which you can enumerate all the component of a CATID.
and ICatRegister interface which provides methods for registering and unregistering component category information in the Registry.
have look on these interfaces in your MSDN , u might find your solution.
Abhishek Srivastava
Software Engg (VC++)
India ,Noida
Mobile no 9891492921
|
|
|
|
|
HI!
I need Yahoo messenger login interface urgently. I want to access yahoo messenger window from my application bypassing the login screen for a particular user. any links or suggestions is most welcome.
|
|
|
|
|
Hi, I need to access COM objects during runtime or dynamically using VC++6. Can somebody please help me in this? Is there a way I can call the COM objects during runtime by entering the GUID or something like that? I am a beginner in COM..
Thx!!
|
|
|
|
|
Is this the function you're looking for?
<code>
CoCreateInstance(REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID * ppv);
</code>
I hope this helps you.
-John
|
|
|
|
|
I forgot to mention you might want to call CoIntialize(NULL) to initialize the COM runtime before making a call to CoCreateInstance(). Once you're through using your COM objects be sure and call CoUnitialize().
|
|
|
|
|
Hi there,
One can access COM objects at run time , but the interface supported by this COM object should
support IDispatch interface.
CLSID objClsid;
// initialize your obj CLSID in this variable
using CoCreateInstance() get the IDispatch pointer.
IDispatch *dispPtr;
CoCreateInstance(objClsid, NULL, CLSCTX_ALL, IID_IDispatch , (void **) &dispPtr);
if your object support IDispatch interface , it will return its instance , else it will return NULL.
now using this dispPtr and IDispatch
int isInfoAvailable;
dispPtr->GetTypeInfoCount(&isInfoAvailable);
if isInfoAvailable = 0 , that means this object does not provide run time type information of interfaces it supports.
if isInfoAvailable = 1 , that mean now you can query for ITypeInfo interface pointer for getting information about the interface this object supports.
now using GetTypeInfo() method you can further query for ITypeInfo interface , using which you can browse all the interface and methods of these interface supported by your COM object.
and then using Invoke and GetIDsOfName methods of IDispatch you can also execute your method at run time.
Regards
Abhishek Srivastava
Software Engg (VC++)
India ,Noida
Mobile no 9891492921
|
|
|
|
|
|
Hello,
I want to learn COM+. I am an intermediate level programmer and am currently learning C#. Can anyone suggest a good book to purchase to learn COM+?
Thanx for the help.
-Flack
|
|
|
|
|
I want to extract Thumbnails Asynchronously...
I use IExtractImage::GetLocation with the flag IEIFLAG_ASYNC .
I get back an E_PENDING which as documented is the sign that things can go on Asynchronously...
I get the object's IRunnableTask (simple QueryInterface )...
And then nothing happens.
IRunnableTask::IsRunning() always returns 0 (which is IRTIR_TASK_NOT_RUNNING ).
IRunnableTask::Run() returns E_NOTIMPL (some documentation said there's no need to call it manually, but anyhows).
So, Can someone tell me what's going wrong here ?
thanks
|
|
|
|
|
Hello Tech people,
Can any one tell me how to create the COM+ components using C#.NET. I wanted to learn about the interface design and deploy the components using C#.NET.
Please let me know, if any one find any kind of material like Gopalan Suresh Raj's website, ie.,
http://gsraj.tripod.com/dotnet/complus/complus.net_accountmanager.html
As a matter of fact, this page it self has some errors. I tried to mail the author from his mail id, but there is no response...
If you come across any of such kind, pl send me the link at my mail id.
You can reach me at SIMIBOLD@YAHOO.COM or SIMIBOLD@HOTMAIL.COM
Thanks,
Simi Agarwal
|
|
|
|
|
I want to develop an word add-in to catch the mouse event of the Word
and determin if the mouse is over some sepecified word or chart,
if true,process it by my own code and the word it's self will not receive the mouse event.
if false,trans the mouse event to the Word
How can I do?
I found all of the Word VBA,and it does not provide the mouse event.
|
|
|
|
|
Hi all,
I m working on designing a Automation Testing tool. I am using MS Active Accessibility for it. I have written some code, with which I can work with windows objects (like search window). I can get and set the text properties, click buttons. But I tried to do the same thing with a C# winForm, but it din't worked.
I am sure that the program is not getting access to objects on the winForm. But I cannot understand why it is working with standays windows objects and not winForms.
any help will be greatly appreciated.
|
|
|
|
|