调用COM对象的问题的综合描述 |
答題得分者是:ha0009
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
上次提到的那个调用C 写的COM对象遇到的问题,经过我的彻底测试,利用各种手段的测试,现在结果如下: 正常情况下,在DELPHI里,Import type library后,调用CoMyCOM.Create,就可以得到 IMyCOM。 但现在对于这个COM对象,则出现 Interface not support 的错误提示。 CoMyCOM.Create实际上是调用了CreateCOMObject 而CreateCOMObject实际上是生成的 IUnknown。 所以,我把程序拆开,写成: MyIUnknown:=CreateCOMObject(xxxx);
运行成功;
然后, MyITestCOM:=MyIUnknown as ITestCOM; <------这里出错。 然后再看,CreateCOMObject是调用的CoCreateInstance,那么,我自己来调用这个函数看看: OleCheck(CoCreateInstance(CLASS_MyTestCOM, nil, CLSCTX_INPROC_SERVER,IID_IMyTestCOM, MyIntf)); 这样调用,结果提示错误:接口不支持。 如果是这样:
OleCheck(CoCreateInstance(CLASS_Netel, nil, CLSCTX_INPROC_SERVER,IUnknown, MyIntf));也就是生成IUnknown,则没问题。 总之,不能生成 IMyTestCOM 这个接口。 而用C 写的调用程序: CoInitializeEx(NULL, 0);
MyTestCOMLib::IMyTestCOM* pMyTestCom = NULL;
HRESULT res = CoCreateInstance(CLSID_MyTestCom, NULL,
CLSCTX_INPROC_SERVER, IID_IMyTestCom,
(void**)&pMyTestCom); 这段C 的程序运行起来,返回结果res=0,则表示生成 IMyTestCom成功。 那么,究竟DELPHI和C 有什么不同呢?
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
经过本版的版主的提示,实验结果如下: 对于这个C 写的COM 它要求必须首先:CoInitializeEx(nil,0) 而不是CoInitialize 而在普通的GUI的程序里,调用 CoInitializeEx 不会成功。有没有其它办法可以成功,我不知道。但我的办法是,把这个放到Project文件的Application.Initialize之前,就可以成功。 然后,在程序的任何地方 CreateCOMObject 来生成这个接口都可以成功了,不会出现 Interface not support 的异常了。
|
ha0009
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:16 回覆:507 積分:639 註冊:2002-03-16 發送簡訊給我 |
補充一下,根據下列節錄自 COMObj.pas 的一段說明,我想是因為 CoInitialize 只能在
application 中呼叫 DLL,但 pcplayer99 的 DLL 只能由 current thread 呼叫,因此必
須藉由 CoInitializeEx 來初始化 COMServ。這是我的一知半解,希望對這方面有研究的夥
伴也能 POST 一些增加我們對 COM 的了解 ^^
{ CoInitFlags determines the COM threading model of the application or current thread. This bitflag value is passed to CoInitializeEx in ComServ initialization. Assign COINIT_APARTMENTTHREADED or COINIT_MULTITHREADED to this variable before Application.Initialize is called by the project source file to select a threading model. Other CoInitializeEx flags (such as COINIT_SPEED_OVER_MEMORY) can be OR'd in also. } var CoInitFlags: Integer = -1; // defaults to no threading model, call CoInitialize() ![]() ![]() |
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
引言: 问题又来了。 如果程序一开始执行了 CoInitializeEx(nil,0),那么,在程序中打开一个 OpenDialog,程序会一直等待,光标一直是 crHourGlass,而 OpenDialog 一直出不来。 看来,问题还没真正解决。这样的COM对象,不知道是否应该是放到另外一个Thread里去,CoInitializeEx也放到那个Thread里去,不影响程序的主Thread?经过试验,CoInitializeEx(nil,COINIT_MULTITHREADED); 上述问题就解决了。看来CoInitializeEx里不同的参数效果很不一样。但具体原因,不同的参数造成的不同的 Thread mode 是如何工作的,我不清楚。请高人大德讲一讲。 |
ha0009
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:16 回覆:507 積分:639 註冊:2002-03-16 發送簡訊給我 |
pcplayer99 你好:
剛剛上微軟的 MSDN 找了CoInitializeEx 的資料,可以上去參考看看。
這是大概的用法,供參考也請先進指導。
執行緒模式常數定義 typedef enum tagCOINIT { COINIT_MULTITHREADED = 0x0, COINIT_APARTMENTTHREADED = 0x2, COINIT_DISABLE_OLE1DDE = 0x4, COINIT_SPEED_OVER_MEMORY = 0x8, } COINIT; COINIT_MULTITHREADED : Initializes the thread for multi-threaded object concurrency (see Remarks). COINIT_APARTMENTTHREADED : Initializes the thread for apartment-threaded object concurrency (see Remarks). COINIT_DISABLE_OLE1DDE : Disables DDE for Ole1 support. COINIT_SPEED_OVER_MEMORY : Trades memory for speed. CoInitialize 定義 HRESULT CoInitialize(LPVOID pvReserved); pvReserved : 保留,在 Delphi 必須為 Nil。 初始化 COM 物件執行緒模式為 STA。 CoInitializeEx 定義 HRESULT CoInitializeEx(void * pvReserved, DWORD dwCoInit); 初始化 COM 物件在指定的執行緒模式。 pvReserved : 保留,在 Delphi 必須為 Nil。 dwCoInit : 執行緒模式常數http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmf_a2c_5iyg.asp http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cme_a2d_4oqc.asp ![]() ![]() |
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
|
achigo
一般會員 ![]() ![]() 發表:6 回覆:15 積分:4 註冊:2005-05-28 發送簡訊給我 |
http://support.microsoft.com/kb/264526/zh-tw
我在官方網站找到正解了 方法一: CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 方法二: CoInitialize(NULL);
------
專注完美近乎苛求~~ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |