150 likes | 276 Views
VC 编写组件中的问题. 1. 在定义函数参数时是否需要使用 retval 。 retval 的作用是把此参数作为函数的返回值。例如: [out,retval] BSTR *p 那就是说,* p 被作为函数的返回值。 可以用在接口成员函数的参数上,或者用在属性接口成员参数上 注意:::: (1) 此属性只能使用在函数的最后一个参数上。 (2) 此参数只能使用在为返回类型的参数 [out] 上,不能使用在 [in] 或者 [inout] 参数上。 (3) 而且此参数必须是指针类型。. VC 编写组件中的问题. 1. 使用此属性
E N D
VC编写组件中的问题 • 1. 在定义函数参数时是否需要使用retval。 retval的作用是把此参数作为函数的返回值。例如: [out,retval] BSTR *p 那就是说,*p被作为函数的返回值。 可以用在接口成员函数的参数上,或者用在属性接口成员参数上 注意:::: (1) 此属性只能使用在函数的最后一个参数上。 (2) 此参数只能使用在为返回类型的参数[out]上,不能使用在[in]或者[inout]参数上。 (3) 而且此参数必须是指针类型。
VC编写组件中的问题 • 1. 使用此属性 如果使用了此属性,那么最后一个参数就被作为函数的返回值,那么在VB中进行调用如下: dim object1 as new hellolib.Greet dim disp as string disp=object1.get_Greeting Text1.text=disp
VC编写组件中的问题 • 2. 不使用此属性 如果不使用此属性,那么就只能从函数调用时的参数中获得此函数的值, 因此在VB中进行调用就要修改,其调用如下: dim object1 as new hellolib.Greet dim disp as string object1.get_Greeting disp Text1.text=disp 此时的disp就被作为函数定义时的参数*p的值,此参数中存什么值,disp就是什么。 作为返回值时可用等号,不作返回值时,只能取获得对应参数的值。
VC编写组件中的问题 • 3.下面的代码将更清楚: 组件的中接口成员函数的定义如下: [helpstring("method get_Greeting")] HRESULT get_Greeting([out] BSTR *p1,[out] BSTR *p2); 实现如下: CComBSTR bstr1("Hello"),bstr2("World"); *p1=bstr1.Detach(); *p2=bstr2.Detach(); return S_OK; 那么*p1和*p2都不作为函数的返回值。
VC编写组件中的问题 • 3. 那么在VB中对其调用就相应如下: Dim object1 As New HelloLib.Greet Dim disp1 As String Dim disp2 As String object1.get_Greeting disp1, disp2 Text2.Text = disp1 Text1.Text = disp2 对应的disp变量就为函数定义中的参数*p1,disp2变量就为函数定义中的参数*p2。
用VC来做客户程序 • 1 . 新建一个MFC Appwizard[exe]工程 • 2. 给一个工程名helloclientc,确定 • 3. 选择基本对话框 • 4. 然后点击完成----确定 • 5. 进入程序编辑状态 • 6. 把生成的组件文件中的hello.tlb从服务器目录拷贝到客户目录中。 • 7. 把下列的include和import语句加入到头文件stdafx.h中。
用VC来做客户程序 • 加入后如下: #include <afxwin.h> #include <afxext.h> #include <afxdisp.h> #import “hello.tlb" no_namespace 其中的import被用来从一个类型库中取出信息,这个被引入的类型库就被转变为正在编写程序的C++类,这一命令最多用来描述COM接口。 • 8. 编译该工程并确认没有错误。 • 9. 通过执行下列CHelloclientcDlg::OnOK()的操作,对COM服务器做一个简单的测试。 创建一个指向COM对象的指针 调用方法get_Greeting 在EDIT中显示字符串
用VC来做客户程序 • 代码如下: // TODO: Add extra validation here IGreetPtr pGreet("hello.Greet.1"); BSTR bstr; bstr=pGreet->get_Greeting(); _bstr_t greeting; greeting=bstr; SetDlgItemText(IDC_EDIT1,greeting);
用VC来做客户程序 • 10.编译并运行客户程序。该程序启动后立即关闭,没有显示任何输出结果。 • 11. 可以对其进行出错处理,处理如下: try{ IGreetPtr pGreet("hello.Greet.1"); BSTR bstr; bstr=pGreet->get_Greeting(); _bstr_t greeting; greeting=bstr; SetDlgItemText(IDC_EDIT1,greeting);} catch(_com_error&ex){ MessageBox(ex.ErrorMessage());}
用VC来做客户程序 • 12. 再编译运行,将得到一个没有初始化OLE的错误信息 • 13. 由于客户程序是MFC类库应用,可以通过调用InitInstance的AfxOleInit来初始化OLE.代码如下: BOOL ChelloclinetcApp::InitInstance() { // Initialize OLE libraries if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } } • 14. 再次编译并运行该程序,该程序就可以正常工作了。这样便可以得到要显示的值。
用VC来做客户程序 • 注意是两个[out]参数,就应如此来处理: try { IGreetPtr pGreet(“hello.greet.1"); BSTR greeting1,greeting2; pGreet->get_Greeting(&greeting1,&greeting2); _bstr_t greet1(greeting1); _bstr_t greet2(greeting2); SetDlgItemText(IDC_EDIT1,greet1); SetDlgItemText(IDC_EDIT2,greet2); } catch(_com_error&ex) { MessageBox(ex.ErrorMessage()); } 参数对应,在此传递的是地址,而非值。