C++ 调用COM 接口函数出错

nearwu 2012-10-27 09:53:04
要实现的功能是调用Arcgis 控件的接口函数。
具体步骤如下:
1.在stdafx.h头文件导入控件:
//import esriGISClient.olb
#import "libid:746F6817-89BB-4490-9829-83CA25FD505A" raw_interfaces_only raw_native_types named_guids exclude("OLE_HANDLE", "OLE_COLOR" ),
在debug目录下已经生产 esriGISClient.tlh 接口文件。
esriGISClient.tlh 内有个IPropertySet类.
IPropertySet : IUnknown
{ // Raw methods provided by interface
virtual HRESULT __stdcall get_Count (
/*[out,retval]*/ long * Count ) = 0;
virtual HRESULT __stdcall GetProperty (
/*[in]*/ BSTR Name,
/*[out,retval]*/ VARIANT * Value ) = 0;
virtual HRESULT __stdcall GetProperties (
/*[in]*/ VARIANT names,
/*[out]*/ VARIANT * values ) = 0;
virtual HRESULT __stdcall GetAllProperties (
/*[out]*/ VARIANT * names,
/*[out]*/ VARIANT * values ) = 0;
virtual HRESULT __stdcall SetProperty (
/*[in]*/ BSTR Name,
/*[in]*/ VARIANT Value ) = 0;
virtual HRESULT __stdcall SetProperties (
/*[in]*/ VARIANT names,
/*[in]*/ VARIANT values ) = 0;
virtual HRESULT __stdcall IsEqual (
/*[in]*/ struct IPropertySet * PropertySet,
/*[out,retval]*/ VARIANT_BOOL * IsEqual ) = 0;
virtual HRESULT __stdcall RemoveProperty (
/*[in]*/ BSTR Name ) = 0;
};
现在就是要调用这个类的方法.
比如我要实现 get_Count,尝试了如下方法
第一种方法:
IPropertySet *mySetData= NULL;
mySetData->get_Count(0);//报错,如下:
//....exe 中的 0x00ad5e01 处未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突.
第二种方法:
IUnknown *pUnk=NULL;
IPropertySet *mySetData=NULL;
CoCreateInstance(CLSID_PropertySet,(LPUNKNOWN)CLSCTX_INPROC_SERVER,NULL,IID_IUnknown,(void **)&pUnk);
pUnk->QueryInterface(IID_IPropertySet,(void**)&mySetData);
//报错,内容同上:
//....exe 中的 0x001f7c50处未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突.
pUnk->Release();
mySetData->get_Count(0);
mySetData->Release();
CoUninitialize();
初学COM,多谢大家赐教!
...全文
363 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
gzp111112 2015-05-12
  • 打赏
  • 举报
回复
学习了,正在研究COM方法。
yisikaipu 2012-10-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

CoCreateInstance(CLSID_PropertySet,(LPUNKNOWN)CLSCTX_INPROC_SERVER,NULL,IID_IUnknown,(void **)&pUnk);

这个函数第一个参数应该传入的是 组件的 GUID 吧, 你这里传入的是接口的GUID
[/Quote]

你这么一提醒才发现楼主参数错了,但不是第一个,而是第二个和第三个颠倒了

CoCreateInstance(CLSID_PropertySet,(LPUNKNOWN)CLSCTX_INPROC_SERVER,NULL,IID_IUnknown,(void **)&pUnk);
改成:
CoCreateInstance(CLSID_PropertySet,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&pUnk);
ouuyang 2012-10-27
  • 打赏
  • 举报
回复
CoCreateInstance 的声明

HRESULT _stdcall CoCreateInstance(REFCLSID rclsid,

LPUNKNOWN pUnkOuter,

DWORD dwClsContext,

REFIID riid,

LPVOID * ppv);



第一个参数:待创建组件的CLSID。

第二个参数:用于聚合组件。

第三个参数:dwClsContext的作用是限定所创建的组件的执行上下文。

第四个参数:iid为组件上待使用的接口的iid。
ouuyang 2012-10-27
  • 打赏
  • 举报
回复
CoCreateInstance(CLSID_PropertySet,(LPUNKNOWN)CLSCTX_INPROC_SERVER,NULL,IID_IUnknown,(void **)&pUnk);

这个函数第一个参数应该传入的是 组件的 GUID 吧, 你这里传入的是接口的GUID
nearwu 2012-10-27
  • 打赏
  • 举报
回复
HKEY_CLASSES_ROOT 里可以找到的,
难道是注册表中的服务器类型损坏? 这个怎么判断和解决?
yisikaipu 2012-10-27
  • 打赏
  • 举报
回复
手动注册后,在注册表里找到了吗?
nearwu 2012-10-27
  • 打赏
  • 举报
回复
CoCreateInstance 函数的返回值 REGDB_E_CLASSNOTREG,没有注册,手动注册后还是一样,分析中
yisikaipu 2012-10-27
  • 打赏
  • 举报
回复
未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突

你用NULL指针调用成员函数。根据C++标准,调用成员函数须解引用指针,而解引用NULL指针,属未定义行为

在Windows上,表现为访问违规,异常编号:0xC0000005

并给出提示:读取位置 0x00000000 时发生访问冲突

这里的0x00000000就是你的NULL,第一个是因为你初始化为NULL后就没变过,第二个是你的CoCreateInstance没有成功
ouuyang 2012-10-27
  • 打赏
  • 举报
回复
第一种方法 mySetData 没有初始化当然报错。(IPropertySet *mySetData= NULL;

第二种方法,你要判断一下各各函数的返回值,不能直接调用,这样不能定位问题
CoCreateInstance 函数的返回值
S_OK
  指定的Com对象实例被成功创建。
  REGDB_E_CLASSNOTREG
  指定的类没有在注册表中注册. 也可能是指定的dwClsContext没有注册或注册表中的服务器类型损坏
  CLASS_E_NOAGGREGATION
  这个类不能创建为聚合型。
  E_NOINTERFACE
  指定的类没有实现请求的接口, 或者是IUnknown接口没有暴露请求的接口.


至于调用方式,第二种是正确的,相关问题你可以看一下一本书
《COM 技术内幕——微软组件对象模型》
nearwu 2012-10-27
  • 打赏
  • 举报
回复
谢谢各位了,网上找的例子就直接照搬了,看来要先搞明白了在用,还需努力学习

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧