線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3223
推到 Plurk!
推到 Facebook!

调用COM对象的问题的综合描述

答題得分者是:ha0009
pcplayer99
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-09 22:24:49 IP:219.133.xxx.xxx 未訂閱
上次提到的那个调用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
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-07-09 23:03:38 IP:61.144.xxx.xxx 未訂閱
上述问题的进一步试验结果: 在DELPHI里New一个Console Application, 然后,同样地照上面的方法做,当然,首先要调用CoInitializeEx(nil,0); 然后,用CreateCOMObject生成 IUnknown 成功。 然后,用 as IMyTestCom,转接口类型,成功。<---这一步,如果是在普通的GUI里做,就失败,提示interface not support.
pcplayer99
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-07-10 00:23:18 IP:61.144.xxx.xxx 未訂閱
经过本版的版主的提示,实验结果如下: 对于这个C 写的COM 它要求必须首先:CoInitializeEx(nil,0) 而不是CoInitialize 而在普通的GUI的程序里,调用 CoInitializeEx 不会成功。有没有其它办法可以成功,我不知道。但我的办法是,把这个放到Project文件的Application.Initialize之前,就可以成功。 然后,在程序的任何地方 CreateCOMObject 来生成这个接口都可以成功了,不会出现 Interface not support 的异常了。
ha0009
版主


發表:16
回覆:507
積分:639
註冊:2002-03-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-07-10 01:17:09 IP:61.56.xxx.xxx 未訂閱
補充一下,根據下列節錄自 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
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-07-11 10:08:15 IP:61.144.xxx.xxx 未訂閱
问题又来了。 如果程序一开始执行了 CoInitializeEx(nil,0),那么,在程序中打开一个 OpenDialog,程序会一直等待,光标一直是 crHourGlass,而 OpenDialog 一直出不来。 看来,问题还没真正解决。这样的COM对象,不知道是否应该是放到另外一个Thread里去,CoInitializeEx也放到那个Thread里去,不影响程序的主Thread?
pcplayer99
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-07-11 10:17:28 IP:61.144.xxx.xxx 未訂閱
引言: 问题又来了。 如果程序一开始执行了 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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-07-11 10:38:37 IP:61.30.xxx.xxx 未訂閱
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
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-07-12 16:27:48 IP:218.18.xxx.xxx 未訂閱
谢谢。
achigo
一般會員


發表:6
回覆:15
積分:4
註冊:2005-05-28

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-22 22:40:13 IP:203.192.xxx.xxx 訂閱
http://support.microsoft.com/kb/264526/zh-tw
我在官方網站找到正解了

方法一:
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
方法二:
CoInitialize(NULL);
------
專注完美近乎苛求~~
系統時間:2017-12-14 6:27:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!