调用 Web 服务的 C++ Builder 控制台应用程序 (hello world)

Edu*_*ard 3 soap web-services c++builder

我正在尝试使用 C++Builder 编写一个“Hello World”示例。这是我的第一个项目,所以我可能犯了一个简单的错误。

我想创建一个调用计算器 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;
}
//---------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

另外,我将肥皂代理添加到 New->Other->WebService->WSDL Importer 中。使用 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
Run Code Online (Sandbox Code Playgroud)

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

---------------------------
Debugger Exception Notification
---------------------------
Project Test.exe raised exception class EOleSysError 
  with message 'CoInitialize has not been called'.
---------------------------
Break   Continue   Help   
---------------------------
Run Code Online (Sandbox Code Playgroud)

调试似乎 GetCalculatorSoap() 执行正常,但在调用 Add 方法之前抛出异常......

任何想法有什么问题吗?谢谢!

Ken*_*ite 5

错误消息告诉您问题是什么——CoInitialize尚未被调用。(实际上,最好还是打电话CoInitializeEx,但两者都可以。)

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

CoInitialize(NULL);您可以通过在函数开头调用 ' 来修复它main。不要忘记CoUnitialize();在结束时main也打电话。

在Delphi中,CoInitialize/CoUninitialize是在ActiveX单元中声明的。在 C++Builder 中,它似乎在 OBJBASE.H 中(快速搜索发现它在那里,这也是 MSDN文档中指出的内容) 。

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