【问题标题】:C++ Builder console application that calls a webservice (hello world)调用 Web 服务的 C++ Builder 控制台应用程序(hello world)
【发布时间】:2012-02-21 19:18:49
【问题描述】:

我正在尝试使用 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;
}
//---------------------------------------------------------------------------

此外,我将soap代理添加到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

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

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

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

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

【问题讨论】:

    标签: web-services soap c++builder


    【解决方案1】:

    错误消息告诉您问题所在 - CoInitialize 尚未被调用。 (实际上,最好调用CoInitializeEx,但两者都可以。)

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

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

    在 Delphi 中,CoInitialize/CoUninitializeActiveX 单元中声明。在 C++Builder 中,它似乎在 OBJBASE.H 中(快速搜索在那里找到了它,这也是 MSDN documentation 中指出的内容。

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

    【讨论】:

    • 非常感谢。习惯了.net编码,我需要重新学习很多低级人员。就像释放内存...
    • 我想知道... SOAP 代码的哪一部分需要 COM? HTTPRIO 需要 COM 才能工作?
    • 我认为这是一部分。我必须查看源代码才能确定,但​​您可以通过它使用的单位和它所基于的接口来判断。我在您的控制台应用程序代码中看不到任何内容,但我确实在 SOAP 代码中看到了对 QueryInterface 的调用,这表明它正在使用 COM。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 2021-08-25
    • 2022-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    相关资源
    最近更新 更多