|
>> And another question, in some of my code, i use another interface witch is provided by ms...
Do you mean that in your ATL COM object class, you implement the MS interface ? E.g. :
class ATL_NO_VTABLE CMyClass :
public ...
public ISomeMSInterface,
public ...
Or do you mean that the actual code :
>> CComPtr pI;
>> HRESULT hr = pI.CoCreateInstance(CLSID_SomeInterface);
is called in some function of your ATL COM object source codes ? E.g. :
STDMETHODIMP CMyClass::SomeMethod()
{
CComPtr pI;
HRESULT hr = pI.CoCreateInstance(CLSID_SomeInterface);
...
}
- Bio.
|
|
|
|
|
No. I really import the interface from the component.
so i directly use that interface like that.
|
|
|
|
|
To confirm, the creation of object of coclass CLSID_SomeInterface is actually called in some function of your ATL COM object source codes, e.g. :
STDMETHODIMP CMyClass::SomeMethod()
{
CComPtr pI;
HRESULT hr = pI.CoCreateInstance();
...
}
- Bio.
|
|
|
|
|
Yes. I packed this code in a static library as .lib.
But, it's strangely that if i direct use the static library, the code will work well( CoCreateInstance returns S_OK). but, if i use the static library in my atl com object and i call that code via the com dll, the CoCreateInstance would returns E_NOINTERFACE.
|
|
|
|
|
The use of a static library makes no difference as far as the creation of COM objects is concerned. Here's what I suggest :
1. Make sure that the correct interface ID is passed in. You'll have to check your source codes to be sure of this.
2. Make sure that the correct version of the target COM DLL is loaded. In debug run mode, use the VC++ "Modules" menu item.
Best of luck,
Bio.
|
|
|
|
|
Of course, they are OK.
Although the problem still remains, but i think it should due to my own fault. Just take it easy.
Thanks
|
|
|
|
|
hi, Bio. I use this method to remove type library information from the dll file successfully. but the target dll(without type library) can't be register successfully without the .tlb file and returns "Error loading library/DLL"
|
|
|
|
|
Hello kcynic,
If you want to remove the type library information from your COM DLL and yet be able to register your COM DLL, the you need to do some more tweaking in your DllRegisterServer() code.
This function is generated for you by ATL and it generally looks like the following :
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(/*TRUE*/ FALSE);
}
Here, as suggested by my code above, comment out the TRUE value and insert in FALSE. The issue is that _Module.RegisterServer() will attempt to perform 2 things :
1. Writes information of the COM objects in your DLL into the registry.
2. Registers the type library (the *.tlb) file generated for you by the MIDL compiler into the registry.
In order to do (2), the type library binary must be part of the resource of your DLL. Now, if you do not wish to register your type library, the FALSE value of the parameter to _Module.RegisterServer() will specifically not register your type library.
- Bio.
|
|
|
|
|
Cool. It really works.
Before post this question, I only know atl only register the component's AppID and clsid, so it would not work if i remove the type library information from the resource. I want to write my own code to register the interfaces by hand before. Now, i know i only just modify a parameter in the existent code.
Thanks very much.
Regards.
|
|
|
|
|
|
This forum is for questions not advertising. If people are interested they will find your article. Stick to the protocols.
|
|
|
|
|
Sorry and thank you. Now the message type has been changed to "News" instead of "Question".
My intent was to spread the word to those who may need it. This include those who use the MFC technolgy, COM and ATL, hence the 3 copies I posted at the three forums.
Respectfully.
Easy Profiler : Now open source !
http://www.codeproject.com/KB/cpp/easyprofiler.aspx
|
|
|
|
|
Ahmed Charfeddine wrote: My intent was to spread the word to those who may need it.
As I said in my previous message, if people are interested they will find it for themselves; the forums should not be used for advertising. You triple post is also triple abuse - stick to the protocols.
|
|
|
|
|
OK I deleted the message.
Easy Profiler : Now open source !
http://www.codeproject.com/KB/cpp/easyprofiler.aspx
|
|
|
|
|
Hi
I have created ATL toolbar in which i creat windows using CreateWindow() with sattic control. I load bmp into this windows by using LoadBitmap. But when I move toolbar , bitmap image get disapper/ flicker.
How to avoid flicker of window with bitmap is loaded into it.
thanks
abm
|
|
|
|
|
#include <algorithm>
#include <fstream>
#include <sstream>
int main()
{
std::fstream fs("d:/test.txt");
std::stringstream ss;
ss << "hello" << std::endl;
std::copy(std::istream_iterator<char>(ss),
std::istream_iterator<char>(),
std::ostream_iterator<char>(fs));
fs.close();
return 0;
}
The code not work, I have some questions:
1. What does this mean: std::istream_iterator<char>() ?
2. Is the position of the stream iterator depent on the current postion of the stream itselft?
Thanks.
3. How to make the code work?
modified on Wednesday, November 4, 2009 9:13 AM
|
|
|
|
|
Firstly - a CP/HTML thing - you need to escape the < characters in the template parameter spec of the iterators (looking at the source of the page, they should be <char> , yes?).
Try declaring fs as a std::ofstream or making sure that the destination file exists - with that change, the code works fine.
std::istream_iterator<char>() is a sentinel value that represents the end of any input stream. Once an istream_iterator<char> steps past the end of the file, it has the same value as std::istream_iterator<char>() .
A stream iterator interacts with the stream position. It's a bad idea to manipulate the stream while there are active stream iterators.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
|
Hello everybody!
Now I installed the WTL8,and clicked "D:\AppWiz\setup80.js" to setup.
I can only use WTL Wizard in VS2005,but I can't see the WTL wizard when I create a new project in VC6.0 ?
thanks for your reply !
|
|
|
|
|
You need to use the Wizard that came with the WTL 7.1[^] - 7.5 and later only support VS2002 or later.
I think you may still be able to use WTL 8, by using the WTL8 include directory in VS6 rather than the WTL 7.1 directory.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
|
I have created an in-process COM object (DLL) using ATL. Note that this is an object and not a control (so has no window or user-interface.) My problem is that I am trying to fire an event from a second thread and I am getting a Catastrophic failure (0x8000FFFF). If I fire the event from my main thread, then I don't get the error. The second thread is calling CoInitializeEx but this makes no difference. I am using the Apartment threading model but switching to Free Threaded doesn't appear to help.
The fact I am trying to do this from a second thread is obviously crucial. Is there an easy way to do this?
For example, in my main object's source file:
STDMETHODIMP MyObject::SomeMethod(...)
{
CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
FireEvent(L"Hello, world!");
return S_OK;
}
DWORD WINAPI ThreadProc(LPVOID param)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
MyObject* comObject = reinterpret_cast<MyObject*>(param);
comObject->FireEvent(L"Hello, world!");
}
void MyObject::FireEvent(BSTR str)
{
...
pConnection->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
}
One idea would be for the main COM object class to create a hidden window and pass the window handle to the thread. The thread could then post a message to the window which would then fire the event. This would ensure the right thread is firing the event. The only problem with this is I don't think there is a message pump running in the case of a simple COM object like this (although I might be wrong) and I have no ideas how to implement one (DLLMain? no ideas.)
|
|
|
|
|
Hello Rob,
The problem is that the client object's event interface pointer (e.g. pConnection in your code snippets) is not transferred to your thread properly. It must be marshaled to the thread function via one of the standard marshaling APIs. The simplest one to use is the IGlobalInterfaceTable interface methods.
I'll follow up with further responses with sample codes that you can use.
Bio.
|
|
|
|
|
As Lim Bio Liong already said, the problem is that the source interface, i.e. the interface that is called from your secondary thread, is not properly marshalled when crossing apartment boundaries.
Like you suggested yourself, you can post a message to the main thread and call the source interface from there.
But there are two other common ways when firing COM events from other threads:
1. Using ::CoMarshalInterThreadInterfaceInStream() [^] and ::CoGetInterfaceAndReleaseStream()
2. Using the Global Interface Table (GIT)
When the interface to be marshalled is a source interface, alternative #1 is useful if you know that all calls will be made from the thread that you've marshalled the interface into.
Alternative #2 is useful when you will be able to call the interface from any thread, or don't know what thread will make the call. But the downside is that it requires a little overhead compared to alternative #1 since you need to "get" the interface for every call.
Michael Lindig has written a very nice ATL solution that I've used for years which uses the GIT.
You'll find it here[^].
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hello Rob,
I've written some utility functions that can help you with working with the Global Interface Table. Email me : bio_lim_2004@yahoo.com
I'll send them to you.
Bio.
|
|
|
|