2012-02-21 198 views
2

我正在尝试使用C++ Builder编写“Hello World”示例。这是我的第一个项目,所以我可能犯了一个简单的错误。调用webservice(hello world)的C++ Builder控制台应用程序

我想创建一个调用计算器Web服务的控制台应用程序。

我打开C++ Builder 2007,创建控制台应用程序。一个称为File1.cpp的cpp文件出现。这里是它的内容:

//--------------------------------------------------------------------------- 
#include <iostream.h> 
#include <vcl.h> 
#pragma hdrstop 
#include "calculator.h" 

//--------------------------------------------------------------------------- 

#pragma argsused 
int main(int argc, char* argv[]) 
{ 
    double a, b; 

    cout << "Enter the values to sum\n"; 
    cout << "A: "; 
    cin >> a; 
    cout << "B: "; 
    cin >> b; 

    cout << "\nA+B:"; 
    cout << GetCalculatorSoap()->Add(1,2); 

    cout << "\n\nPress any key to continue..."; 
    getchar(); 

    return 0; 
} 
//--------------------------------------------------------------------------- 

另外我添加了进入New-> Other-> WebService-> WSDL Importer的soap代理。 使用WSDL http://www.dneonline.com/calculator.asmx?WSDL

这个动作加入calculator.cpp:

// ************************************************************************ // 
// The types declared in this file were generated from data read from the 
// WSDL File described below: 
// WSDL  : http://www.dneonline.com/calculator.asmx?WSDL 
// >Import : http://www.dneonline.com/calculator.asmx?WSDL:0 
// Encoding : utf-8 
// Version : 1.0 
// (21/02/2012 19:48:31 - - $Rev: 10138 $) 
// ************************************************************************ // 

#include <vcl.h> 
#pragma hdrstop 

#if !defined(calculatorH) 
#include "calculator.h" 
#endif 

namespace NS_calculator { 

_di_CalculatorSoap GetCalculatorSoap(bool useWSDL, 
    AnsiString addr, THTTPRIO* HTTPRIO) 
{ 
    static const char* defWSDL= "http://www.dneonline.com/calculator.asmx?WSDL"; 
    static const char* defURL = "http://www.dneonline.com/calculator.asmx"; 
    static const char* defSvc = "Calculator"; 
    static const char* defPrt = "CalculatorSoap"; 
    if (addr=="") 
    addr = useWSDL ? defWSDL : defURL; 
    THTTPRIO* rio = HTTPRIO ? HTTPRIO : new THTTPRIO(0); 
    if (useWSDL) { 
    rio->WSDLLocation = addr; 
    rio->Service = defSvc; 
    rio->Port = defPrt; 
    } else { 
    rio->URL = addr; 
    } 
    _di_CalculatorSoap service; 
    rio->QueryInterface(service); 
    if (!service && !HTTPRIO) 
    delete rio; 
    return service; 
} 


// ************************************************************************ // 
// This routine registers the interfaces and types exposed by the WebService. 
// ************************************************************************ // 
static void RegTypes() 
{ 
    /* CalculatorSoap */ 
    InvRegistry()->RegisterInterface(__interfaceTypeinfo(CalculatorSoap),    
    L"http://tempuri.org/", L"utf-8"); 
    InvRegistry()->RegisterDefaultSOAPAction(__interfaceTypeinfo(CalculatorSoap), 
    L"http://tempuri.org/%operationName%"); 
    InvRegistry()->RegisterInvokeOptions(__interfaceTypeinfo(CalculatorSoap), 
    ioDocument); 
} 
#pragma startup RegTypes 32 

};  // NS_calculator 

当我运行应用程序在调用GetCalculatorSoap()时,会引发异常 - >添加(1,2):

--------------------------- 
Debugger Exception Notification 
--------------------------- 
Project Test.exe raised exception class EOleSysError 
    with message 'CoInitialize has not been called'. 
--------------------------- 
Break Continue Help 
--------------------------- 

调试它看起来GetCalculatorSoap()执行正常,但在调用Add方法之前抛出异常...

任何想法有什么不对?谢谢!

回答

4

错误信息告诉你问题是什么 - CoInitialize尚未被调用。 (实际上,最好调用CoInitializeEx代替,但两者都可以。)

您的SOAP代码使用的是COM方法,因此COM必须先被初始化。这是在每个线程的基础上完成的。

您可以在main函数的开始处通过调用CoInitialize(NULL);'来修复它。不要忘记在main的末尾也打电话CoUnitialize();

在Delphi中,CoInitialize/CoUninitializeActiveX单位中声明。在C++ Builder中,它似乎在OBJBASE.H中(快速搜索发现它在那里,并且这也是MSDN documentation中指示的内容

(如果您习惯于编写基于VCL表单的应用程序,以前不会看到这个; VCL自动为你初始化COM,你现在看到它是因为你正在编写一个控制台应用程序。)

+0

非常感谢。用于编码.net,我需要重新学习很多低级员工,像释放内存...... – Eduard 2012-02-22 08:29:42

+0

我想知道...... SOAP代码的哪一部分需要COM?HTTPRIO需要COM工作? – Eduard 2012-02-23 08:47:20

+0

我认为这是部分,我必须看看确保源代码,但你可以通过它使用的单元和它所基于的接口来告诉它。在我看到的控制台应用程序代码中没有任何东西,但我确实在SOAP代码中看到了对“QueryInterface”的调用,这表明它正在使用COM。 – 2012-02-23 11:59:42