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

发布于 2025-01-07 14:00:19 字数 3708 浏览 1 评论 0原文

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

另外,我添加了肥皂代理进入 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 方法之前,抛出了异常...

你知道出了什么问题吗?谢谢!

I am trying write a "Hello World" example using C++Builder. This is my first project so I have probably made a simple mistake.

I want to create a console application that calls a calculator web service.

I open C++Builder 2007 and I create a Console Application. A cpp file called File1.cpp appears. Here it is the content:

//---------------------------------------------------------------------------
#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;
}
//---------------------------------------------------------------------------

Additionally I added the soap proxy going into New->Other->WebService->WSDL Importer.
Using the WSDL http://www.dneonline.com/calculator.asmx?WSDL

This action added 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

When I run the application it raises an exception when calling GetCalculatorSoap()->Add(1,2):

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

Debugging it seems the GetCalculatorSoap() executes ok, but just before calling the Add method the exception is thrown...

Any ideas what is wrong? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遇到 2025-01-14 14:00:19

错误消息告诉您问题是什么 - 尚未调用 CoInitialize。 (实际上,最好改为调用 CoInitializeEx,但两者都可以。)

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

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

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

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

The error message tells you what the problem is - CoInitialize has not been called. (Actually, it's preferable to call CoInitializeEx instead, but either will work.)

Your SOAP code is using COM methods, and therefore COM has to be initialized first. This is done on a per-thread basis.

You can fix it by calling CoInitialize(NULL);' at the beginning of your main function. Don't forget to call CoUnitialize(); at the end of main as well.

In Delphi, CoInitialize/CoUninitialize are declared in the ActiveX unit. In C++Builder, it seems to be in OBJBASE.H (a quick search found it there, and that's also what's indicated in the MSDN documentation.

(If you're used to writing VCL form based apps, you won't have seen this before; the VCL initializes COM for you automatically. You're seeing it now because you're writing a console app.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文