VC中怎么使用COM组件?
最好是能在Console Application(without MFC support)中使用。
假如我有一个组件Com1.dll实现一个接口IMyCom1如下:
interface IMyCom1 : IDispatch
{
Func1();
};
怎么在程序中调用Com1.dll中IMyCom1的Func1()方法?
最好不要使用#import "Com1.dll" no_namespace的方法,因为这样必须在编译时指定使用的dll,岂不是还不如用一般的动态连接库,还能运行时LoadLibrary()?
问题点数:100、回复次数:31Top
1 楼wagnerwash()回复于 2002-02-26 14:16:07 得分 0
高手牛人,急急如律令!Top
2 楼flounder(一肩挑尽万古愁)回复于 2002-02-26 14:29:06 得分 5
你把接口在主框架中实例化,就可以了Top
3 楼finix(*_*)回复于 2002-02-26 14:44:41 得分 40
#incluide "..\*.c"
#include "..\*.h"
int main(....)
{
HRESULT hr;
IMyCom1 *pMyCom1=NULL;
CoInitialize(NULL);
hr=CoCreateInstance(
CLSID_MyCom1
NULL,
CLSCTX_INPROC_SERVER;
IID_IMyCom1,
(void**)&pMyCom1);
if(!SUCCEEDED(hr))
{
.....
}
else
{
pMyCom1->Func();
pMyCom1->Release()
pMyCom1=NULL;
}
CoUninitialize()
return 0;
}
或许对的
Top
4 楼wagnerwash()回复于 2002-02-26 15:52:08 得分 0
to finix:
谢谢!
你的方法可行,但是怎么从Com1.dll生成Com1.h和Com1_i.c?
假如实现IMyCom1接口的组件要求运行时由用户指定(用户输入dll文件名或已注册的CLSID),又应该怎么做?Top
5 楼finix(*_*)回复于 2002-02-26 16:00:32 得分 0
由MIDL编译而成
#import智能指针Top
6 楼pazen()回复于 2002-02-26 16:07:26 得分 0
学习中Top
7 楼wagnerwash()回复于 2002-02-26 16:25:48 得分 0
to finix:
MIDL是把idl文件编译成.h、.c文件,可是怎么从dll文件反编成.h、.c文件呢。
#import智能指针是什么意思?请大侠详细说说。Top
8 楼finix(*_*)回复于 2002-02-26 16:52:37 得分 5
#import智能指针生成的所有接口都以_com_ptr_t摸版为基础。
后者封装了IUnknown方法queryinterface(),addref(),release()和自己的函数
智能指针一般用于客户端,而原始接口用于服务器端,尽量不要混用,以免找成引用记数的错误导致内存泄露,崩溃。。。。Top
9 楼bskay() bskay() bskay()回复于 2002-02-26 16:53:10 得分 0
#import d:\...\the.dll
就可以了Top
10 楼bskay() bskay() bskay()回复于 2002-02-26 16:54:44 得分 0
dll里面有关于如何产生.h(.tlh) .c(.tli)信息的东东的Top
11 楼wagnerwash()回复于 2002-02-26 17:05:54 得分 0
能不能在运行时仅仅根据一个Dll的文件名或CLSID就搞定?生成.h、.c文件还是要在编译时进行。如果不能在运行时由用户指定实现IMyCom1的dll,用COM还不如用一般的dll导出函数呢。
finix大侠能不能给出一个像上面那样的例子?Top
12 楼kimryo(God is on my side)回复于 2002-02-26 17:14:53 得分 15
只用progid就行了,但麻烦很多。XXX.h和XXX_i.c是MIDL.exe编译.idl文件生成的,.tlb文件是二进制的用于在VB或java中的调用。所以你应该在另一个工程中包含XXX.h和XXX_i.c,这样可以直接用你的IMyCom1* pMyCom=NULL;来定义指针、和使用接口ID:IID_IMyCom1常量等。你要示例工程我可以发给你。Top
13 楼idoloveyou(从高二开始上CSDN的人现在都工作了)回复于 2002-02-26 17:18:07 得分 5
你非要指定.dll文件名,又为什么非要用COM呢
直接LoadLibrary,然后GetProcAddress不久得了Top
14 楼wagnerwash()回复于 2002-02-26 17:34:35 得分 0
谢谢大家热情参与,我只能给100分,因此将在问题告一段落后给分。
有代码可以发到wagnerwash@sohu.comTop
15 楼wagnerwash()回复于 2002-02-26 17:38:27 得分 0
to idoloveyou:
不一定是指定文件名,指定CLSID也可以。总之要在运行时确定。所以编译*.h、*_i.c的方法不行。
GetProcAddress()的方法详细的说来怎么做?是不是就是一般的dll导出函数?那样我也知道怎么做。之所以想用COM就是不想有“DLL地狱”的麻烦。Top
16 楼idoloveyou(从高二开始上CSDN的人现在都工作了)回复于 2002-02-26 21:31:15 得分 30
那你就不用那么麻烦了
你既然有IMyCom1的定义和组建的CLSID,那就可以得到IID_IMyCom1(查询注册表,可以从CLSID查到IID,观察一下注册表就可以了),就根本不需要#include什么*.h, *.c的文件
直接CoCreateInstance(CLSID_Component, NULL, CLSCTX_ALL_SERVER, IID_IMyCom1, (void**) &ppv)不就可以了吗Top
17 楼han012(阿毛)回复于 2002-02-27 09:10:24 得分 0
markTop
18 楼erlei1978(二雷)回复于 2002-02-27 13:04:44 得分 0
upTop
19 楼spdia(spdia)回复于 2002-02-27 13:12:21 得分 0
只要你实现的每个Com对象中都有IMyCom1接口,并且有IMyCom1的声明和IID_IMyCom1,就可以CoCreateInstance(CLSID_Component, NULL, CLSCTX_ALL_SERVER, IID_IMyCom1, (void**) &ppv),#import需要dll中有类型库,他才能生成包裹类。Top
20 楼lostall(鸟人)回复于 2002-02-27 15:46:52 得分 0
#import "progid:..." no_namespace named_guids
用progid,避免直接引入dll路径名。
具体可查MSDNTop
21 楼shuxh(shuxh)回复于 2002-02-27 17:27:01 得分 0
kimryo,
麻烦也给我一份例子程序,谢谢Top
22 楼shuxh(shuxh)回复于 2002-02-27 17:29:06 得分 0
kimryo,
麻烦也给我一份例子程序,谢谢
shuxh@163.net
Top
23 楼lgs(老臭虫)回复于 2002-02-27 17:29:46 得分 0
看看MSDN中使用ADO的例子就一切解决了!Top
24 楼shuxh(shuxh)回复于 2002-02-27 17:30:14 得分 0
kimryo,
麻烦也给我一份例子程序,谢谢
shuxh@163.net
Top
25 楼shuxh(shuxh)回复于 2002-02-27 17:31:25 得分 0
kimryo,
麻烦也给我一份例子程序,谢谢
shuxh@163.netTop
26 楼kevin_wang(砸锅卖铁)回复于 2002-02-27 20:44:48 得分 0
wang9658@263.netTop
27 楼tpProgramer(tp编程者)回复于 2002-02-28 08:44:45 得分 0
讨论的很热烈.
帮你们推.Top
28 楼luketang(Luke)回复于 2002-02-28 10:47:37 得分 0
不改了,自个凑合着看吧:
CLSID clsid;
LPCLASSFACTORY pClf;
LPUNKNOWN pUnk;
HRESULT hr;
IDispatch * pdisp;
//查找CLASS ID
if ((::CLSIDFromProgID(L"SecurityMarket.NewsCenter.1", &clsid)) != NOERROR)
{
return;
}
//产生类工厂
if ((::CoGetClassObject(clsid, CLSCTX_SERVER,
NULL, IID_IClassFactory, (void **) &pClf)) != NOERROR)
{
return;
}
//创建IUnknown指针
pClf->CreateInstance(NULL, IID_IUnknown, (void**) &pUnk);
hr = pUnk->QueryInterface(IID_IDispatch, (void**)&pdisp);
WCHAR *pMethodName = L"NewsList";
DISPID dispid;
DISPPARAMS dispparams;
VARIANTARG params[3];
VARIANT result;
CString ParamText;
EXCEPINFO ExceptInfo;
// Get dispatch ID corrisponding to method name.
hr = pdisp->GetIDsOfNames(IID_NULL, &pMethodName, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if(FAILED(hr))
{
TRACE(_T("Cannot get dispatch id of calc method."), hr);
return;
}
VariantInit(¶ms[0]);
params[0].vt = VT_I4;
params[0].intVal = 1001;
VariantInit(¶ms[1]);
params[1].vt = VT_I4;
params[1].intVal = 2;
VariantInit(¶ms[2]);
params[2].vt = VT_I4;
params[2].intVal = 1;
// Initialize DISPPARAMS structure.
dispparams.cArgs = 3;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.rgvarg = params;
// Prepare result variant.
VariantInit(&result);
// Invoke the specified method.
hr = pdisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, &result, &ExceptInfo, NULL);
if(FAILED(hr))
{
TRACE(_T("Invoke of calc method failed."));
}
else
{
// Convert result to a string.
VariantChangeType(&result, &result, 0, VT_BSTR);
// Display result.
//AfxMessageBox(CString(result.bstrVal));
*pCtxt << _T(CString(result.bstrVal));
}
// Clean up variants.
VariantClear(&result);
VariantClear(¶ms[0]);
VariantClear(¶ms[1]);
VariantClear(¶ms[2]);Top
29 楼luketang(Luke)回复于 2002-02-28 10:50:53 得分 0
传入"SecurityMarket.NewsCenter"就可以调用本地的COM了。
最近用了SOAP,很方便。
但不知怎么样最方便地调用其他机器的COM?(即DCOM)Top
30 楼Ashura(阿修罗)回复于 2002-02-28 12:46:14 得分 0
参与一把……Top
31 楼kissfire(kissfire)回复于 2002-02-28 17:48:40 得分 0
signTop




