关于C++编写com和调用com组件的小例子以及个人所犯错误见解

最近在完成研究生课程面向对象方法的第一次作业编写一个com:

环境Visual Studio 2015

一、构造COM组件,项目名称为ComZhh,过程

进入VS,选择左上角的文件,点击新建项目->Visual C++->ATL->ATL项目

注意在下一步中勾选支持com+1.0

接着你讲看到项目下有两个目录

不要着急,你只需要关注ATLProject1即可。然后,你需要开始定义组件内部的类,也就是你的组件的功能部分,我只讲解定义一个功能的内容。在你的项目下,右键添加->添加类->ATL->ATL简单对象

在此后注意下图中的ProgID这一栏,填写完类名之后你需要给你的组件一个名称,它是唯一的,在C++d额客户程序中查找你所定义的类的时候至关重要,

我定义的名称为hello.important,要着重强调。然后点击完成即可,然后注意要找到你的解决方案资源管理器中的类视图!注意 是类视图。

在类视图中可以看到刚刚定义的hello类,但是名称和我们实际定义的不太一样,变成了Chello和Ihello,不过不用担心,你不需要在意,你只需要在Ihello也就是你的类的接口类上右键,->添加->添加方法,定义你所需要的函数

我们可以看到out、retval那两个地方是灰色的,并且在我所看到的教程中大多数人没有提到如何使用,因为out模块代表的是函数的返回值,如果不定义out特性的参数,则无法获得调用函数所获得的返回值。因此我们需要定义一个指针类型的参数,

当你选择了指针类型的参数类型后,out和retval会自动变成可选的,此时在out上打勾,表明zheli这个参数是用来获取返回值的。

也就是现在这个样子,此时你可以看到你的类和接口类中同时都存在了hahaha函数的定义

此后开始实现你的方法

Chello就是你所定义的hello,只是说在头文件中系统自动定义成了Chello类而已 ,并不影响理解和使用。return S_OK是com组件中任意函数的返回值,【out】特性才是返回值,这也可以保证一个函数可以有多个输出值

此时com组件就定义完成了,点击生成->生成解决方案

此时可以在代码的项目目录中看到dll 文件,使用管理员运行cmd,进入dll所在目录执行

regsvr32   “ATLProject1.dll” 将dll添加到注册表中即可。

下面介绍如何通过C++调用com组件

首先新建一个win32的控制台应用程序

直接点击完成即可,然后复制你要调用的dll文件到vs的目录下面,因为如果不这么做vs中c++的import会提示无法打开源文件(.tlh)如下:

然后进入ConsoleApplication1.cpp构建调用函数

此时会显示C1083的错误,注意在这里我犯了错误,因为dll添加进项目的步骤应该是先将dll复制到项目文件夹下然后再vs中的项目中点击添加->添加现有项,选择你将要使用的dll文件,点击添加。

当你这么执行了添加操作之后,仍然会提示无法打开.tlh文件,这可能是vs的小bug?不要着急,接下来直接点击 生成->清理解决方案 然后点击 生成->重新生成解决方案,你会发现此时错误以及程序中import下的红线神奇的消失了,此时import就已经成功了,你可以开始尽情调用了。噢 对 应该是#import"ComZhh.dll" no_namespace ,后面的no_namespace应该也挺重要的,虽然还不是太懂,毕竟刚刚接触QAQ。

 

int main()
{
	
	CoInitialize(NULL);
	 CLSID clsid;
	 CLSIDFromProgID(OLESTR("hello.important"), &clsid);//!!!!!这个是你创建ATL的时候定义的 
     //progid!不要被网上的“dll名称+接口”误导!!!这个地方只要写错不管怎么调试都无法调用dll
	CComPtr<Ihello> pHello;//智能指针
	pHello.CoCreateInstance(clsid);
	Long* result;
	pHello->hahaha(&result);

	pHello.Release();//小心哦!!请看最后的“注意”
	CoUninitialize();


    return 0;
}

填写完成代码之后直接调试就ok啦

如果是bstr*的result有如下的操作需要注意:

        BSTR result;
	pShoot->showShoot(&result);	
	char* resultConvert=_com_util::ConvertBSTRToString(result);
	std::cout << resultConvert;
	SysFreeString(result); // 用完释放 
	delete[] resultConvert;

当result也就是函数中定义的返回值有bstr*类型时,需要进行转换,因为cout无法直接输出bstr类型的内容,需要先通过上面的第三行的转换函数转换为一个字符数组然后再通过std::cout进行输出,之所以没有直接cout是因为上面用了no_namepsace所以没有定义using namespace std;

 

上述操作做完后直接生成然后执行就可以啦!如果有理解不到位的请各位指正,谢谢大家!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章