WSDL 및 서비스 계약

Wsutil.exe 유틸리티는 제공된 WSDL 메타데이터에 따라 C 언어 스텁을 생성하고 사용자가 작성한 XML 스키마에서 설명하는 데이터 형식에 대한 데이터 형식 정의 및 설명을 생성합니다.

다음은 다음 논의의 기초 역할을 하는 WSDL 문서 및 XML 스키마의 예입니다.

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
  <xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified" 
  targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="SimpleMethod">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="a" type="xs:int" />
      <xs:element name="b" type="xs:int" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="SimpleMethodResponse">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="b" type="xs:int" />
      <xs:element name="c" type="xs:int" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:schema>
 </wsdl:types>
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   <wsdl:input wsaw:Action="http://Example.org/ISimpleService/SimpleMethod" 
   message="tns:ISimpleService_SimpleMethod_InputMessage" />
   <wsdl:output wsaw:Action="http://Example.org/ISimpleService/SimpleMethodResponse" 
   message="tns:ISimpleService_SimpleMethod_OutputMessage" />
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:binding name="DefaultBinding_ISimpleService" type="tns:ISimpleService">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="SimpleMethod">
   <soap:operation soapAction="http://Example.org/ISimpleService/SimpleMethod" 
   style="document" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="SimpleService">
  <wsdl:port name="ISimpleService" binding="tns:DefaultBinding_ISimpleService">
   <soap:address location="http://Example.org/ISimpleService" />
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>

이 예제에서는 단일 메서드인 SimpleMethod를 사용하여 계약 ISimpleService를 제공합니다. "SimpleMethod"에는 클라이언트에서 서비스로 전송되는 정수와 b 형식 의 두 입력 매개 변수가 있습니다. 마찬가지로 SimpleMethod에는 성공적으로 완료된 후 클라이언트에 반환되는 형식 수 bc의 두 출력 매개 변수가 있습니다. SAL 주석이 추가된 C 구문에서 메서드 정의는 다음과 같이 표시됩니다.

void SimpleMethod(__in int a, __inout int *  b, __out int * c );

이 정의에서 ISimpleService는 단일 서비스 작업인 SimpleMethod를 사용하는 서비스 계약입니다.

출력 헤더 파일에는 외부 참조에 대한 정의 및 설명이 포함되어 있습니다. 다음 내용이 포함됩니다.

애플리케이션이 참조할 수 있는 스키마 유형 및 서비스 모델 형식에 대한 모든 전역 설명을 캡슐화하기 위해 하나의 전역 구조가 생성됩니다. 구조체의 이름은 정규화된 파일 이름을 사용하여 지정됩니다. 이 예제에서 Wsutil.exe는 모든 웹 서비스 설명을 포함하는 "example_wsdl"이라는 전역 정의 구조를 생성합니다. 구조 정의는 스텁 파일에 생성됩니다.

typedef struct _example_wsdl
{
  struct {
    WS_ELEMENT_DESCRIPTION SimpleMethod;
    WS_ELEMENT_DESCRIPTION SimpleMethodResponse;
  } elements;
  struct {
    WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_InputMessage;
    WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_OutputMessage;
  } messages;
  struct {
    WS_CONTRACT_DESCRIPTION DefaultBinding_ISimpleService;
  } contracts;
} _example_wsdl;

extern const _stockquote_wsdl stockquote_wsdl;

XSD(XML 스키마 문서)의 전역 요소 정의의 경우 각 요소에 대해 하나의 WS_ELEMENT_DESCRIPTION 프로토타입과 해당 C 형식 정의가 생성됩니다. SimpleMethod 및 SimpleMethodResponse에 대한 요소 설명의 프로토타입은 위의 구조에서 멤버로 생성됩니다. C 구조는 다음과 같이 생성됩니다.

typedef struct SimpleMethod
{
  int   a;
  int   b;
} SimpleMethod;

typedef struct SimpleMethodResponse
{
  int   b;
  int   c;
} SimpleMethodResponse;

마찬가지로 전역 복합 형식의 경우 Wsutil.exe는 일치하는 요소 설명 없이 위와 같은 C 형식 구조 정의를 생성합니다.

WSDL 입력의 경우 Wsutil.exe는 다음 프로토타입 및 정의를 생성합니다.

  • 메시지 설명에 대한 WS_MESSAGE_DESCRIPTION 프로토타입이 생성됩니다. 이 설명은 메시지 계층뿐만 아니라 서비스 모델에서도 사용할 수 있습니다. 메시지 설명 구조는 전역 구조에서 "messagename"이라는 필드입니다. 이 예제에서 메시지 설명은 WSDL 파일에 지정된 대로 ISimpleService_SimpleMethod_InputMessage 구조의 ISimpleService_SimpleMethod_InputMessage 필드로 생성됩니다.
  • WS_CONTRACT_DESCRIPTION 프로토타입은 계약 설명에 대해 생성됩니다. 이 설명은 서비스 모델에서 사용됩니다. 계약 설명 구조는 전역 구조에서 "contractname"이라는 필드입니다. 이 예제에서는 계약 설명이 "_example_wsdl" 구조의 DefaultBinding_ISimpleService 필드로 생성됩니다.

작업 및 형식 사양은 프록시와 스텁 모두에 공통적으로 적용되며 두 파일 모두에서 생성됩니다. Wsutil.exe는 프록시와 스텁이 모두 동일한 파일에 생성된 경우에만 하나의 복사본을 생성합니다.

식별자 생성

위에 나열된 자동 생성된 C 구조체는 WSDL 파일에 지정된 이름을 기반으로 만들어집니다. XML NCName은 일반적으로 유효한 C 식별자로 간주되지 않으며 필요에 따라 이름이 정규화됩니다. 16진수 값은 변환되지 않으며 ':', '/' 및 '.'와 같은 일반 문자는 가독성을 향상시키기 위해 밑줄 '_' 문자로 변환됩니다.

스텁의 헤더

서비스 계약의 각 작업에 대해 "<operationname>Callback"이라는 하나의 콜백 루틴이 생성됩니다. 예를 들어 예제 서비스 계약의 "SimpleMethod" 작업에는 "SimpleMethodCallback"이라는 생성된 콜백이 있습니다.

typedef HRESULT (CALLBACK *SimpleMethodCallback) (
  const WS_OPERATION_CONTEXT * context,
  int a, int *b, int *c,
  const WS_ASYNC_CONTEXT *asyncContext,
  WS_ERROR * error);

각 WSDL portType Wsutil.exe에 대해 portType나타내는 함수 테이블을 생성합니다. portType각 작업에는 함수 테이블에 있는 콜백에 대한 해당 함수 포인터가 있습니다.

struct ISimpleServiceMethodTable
{
  ISimpleService_SimpleMethodCallback SimpleMethod;
};

프록시 프로토타입은 모든 작업에 대해 생성됩니다. 프로토타입 이름은 서비스 계약의 WSDL 파일에 지정된 작업 이름(이 경우 "SimpleMethod")입니다.

HRESULT WINAPI SimpleMethod(WS_CHANNEL *channel,
  WS_HEAP *heap,
  int a,
  int *b,
  int *c,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR * error );

로컬 전용 설명 프로토타입 생성

프록시 및 스텁 파일에는 로컬 전용 설명 및 클라이언트 프록시/서비스 스텁 구현이 포함된 구조체에 대한 프로토타입 및 정의를 포함하여 전역 정의 구조에 대한 정의가 포함됩니다.

스텁 파일에 로컬인 모든 프로토타입 및 정의는 캡슐화 구조의 일부로 생성됩니다. 이 중요한 로컬 설명 구조는 serialization 계층 및 서비스 모델에 필요한 설명의 명확한 계층 구조를 제공합니다. 로컬 설명 구조에는 아래와 유사한 프로토타입이 있습니다.

struct _filenameLocalDefinitions
{
  struct {
  // schema related output for all the embedded 
  // descriptions that needs to describe global complex types.
  } globalTypes;
  // global elements.
  struct {
  // schema related output, like field description
  // structure description, element description etc.
  ...
  } globalElements;
  struct {
  // messages and related descriptions
  } messages;
  struct {
  // contract and related descriptions.
  } contracts;
  struct {
  // XML dictionary entries.
  } dictionary;
} _filenameLocalDefinitions;

다른 파일에서 정의 참조

로컬 정의는 다른 파일에서 생성된 설명을 참조할 수 있습니다. 예를 들어 WSDL 파일에서 생성된 C 코드 파일에서 메시지를 정의할 수 있지만 메시지 요소는 XSD 파일에서 생성된 C 코드 파일의 다른 위치에서 정의될 수 있습니다. 이 경우 Wsutil.exe는 아래와 같이 메시지 정의를 포함하는 파일에서 전역 요소에 대한 참조를 생성합니다.

{  // WS_MESSAGE_DESCRIPTION
...
(WS_ELEMENT_DESRIPTION *)b_xsd.globalElement.<elementname>
  };

전역 요소 설명

wsdl:type 또는 XSD 파일에 정의된 각 전역 요소에 대해 GlobalElement 필드 내에 elementName이라는 일치하는 필드가 있습니다. 이 예제에서는 SimpleMethod라는 구조체가 생성됩니다.

typedef struct _SimpleServiceLocal
{
  struct  // global elements
  {
    struct // SimpleMethod
    {
    ...
    WS_ELEMENT_DESCRIPTION SimpleMethod;
    } SimpleMethod;
    ...
  } globalElements;
}

요소 설명에 필요한 다른 설명은 포함하는 구조의 일부로 생성됩니다. 요소가 단순 형식 요소인 경우 WS_ELEMENT_DESCRIPTION 필드가 하나만 있습니다. 요소 형식이 구조체인 경우 모든 관련 필드 및 구조 설명이 요소 구조의 일부로 생성됩니다. 이 예제에서 SimpleMethod 요소는 a와 b라는 두 개의 필드를 포함하는 구조체입니다. Wsutil.exe는 다음과 같이 구조를 생성합니다.

...
struct // SimpleMethod
{
  struct // SimpleMethod structure
  {
    WS_FIELD_DESCRIPTION a;
    WS_FIELD_DESCRIPTION b;
    WS_FIELD_DESCRIPTION * SimpleMethodFields [2];
    WS_STRUCT_DESCRIPTION structDesc;
  } SimpleMethoddescs; // SimpleMethod
  WS_ELEMENT_DESCRIPTION elementDesc;
} SimpleMethod;
...

포함된 구조체 및 포함된 요소는 필요에 따라 하위 구조로 생성됩니다.

Wsutil.exe는 지정된 wsdl:service 아래에 정의된 각 portType 값에 대한 WSDL 섹션 아래에 필드를 생성합니다.

...
struct { // WSDL
    struct { // portTypeName
        struct { // operationName
        } operationName;
    ...
    WS_OPERATION_DESCRIPTION* operations[numOperations];
    WS_CONTRACT_DESCRIPTION contractDesc;
    } portTypeName;
}
...

Wsutil.exe는 작업에 필요한 모든 설명, 각 메서드에 대한 각 작업 설명에 대한 포인터의 기호 배열 및 지정된 portType에 대한 하나의 WS_CONTRACT_DESCRIPTION 포함하는 하나의 필드 f를 생성합니다.

작업에 필요한 모든 설명은 지정된 portType 아래의 operationName 필드 내에서 생성됩니다. 여기에는 입력 및 출력 매개 변수의 하위 구조뿐만 아니라 WS_ELEMENT_DESCRIPTION 필드도 포함됩니다. 마찬가지로 입력 메시지 및 선택적 출력 메시지에 대한 WS_MESSAGE_DESCRIPTION 필드가 다음과 함께 포함됩니다.작업 자체의 모든 작업 매개 변수 및 WS_OPERATION_DESCRIPTION 필드에 대한 목록 필드를 WS_PARAMETER_DESCRIPTION. 이 예제에서는 아래와 같이 SimpleMethod 설명의 코드 구조가 생성됩니다.

...
struct // messages
{
  WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_InputMessage;
  WS_MESSAGE_DESCRIPTION ISimpleService_SimpleMethod_OutputMessage;
} messages;
struct // contracts
{
  struct // DefaultBinding_ISimpleService
  {
    struct // SimpleMethod
    {
      WS_PARAMETER_DESCRIPTION params[3];
      WS_OPERATION_DESCRIPTION SimpleMethod;
    } SimpleMethod;
    WS_OPERATION_DESCRIPTION* operations[1];
    WS_CONTRACT_DESCRIPTION contractDesc;
  } DefaultBinding_ISimpleService;
} contracts;
...

다양한 설명에 사용되는 이름 및 네임스페이스는 WS_XML_STRING 형식의 필드로 생성됩니다. 이러한 모든 문자열은 파일별 상수 사전의 일부로 생성됩니다. 문자열 목록과 WS_XML_DICTIONARY 필드(아래 예제의 dict)는 fileNameLocal 구조체의 사전 필드의 일부로 생성됩니다.

struct { // fileNameLocal
...
  struct { // dictionary
    struct { // XML string list
      WS_XML_STRING firstFieldName;
      WS_XML_STRING firstFieldNS;
      ...
    } xmlStrings;
  WS_XML_DICTIONARY dict;
  } dictionary;
}; // fileNameLocal;

WS_XML_STRING배열은 사용자에게 친숙한 이름으로 명명된 일련의 WS_XML_STRING 형식 필드로 생성됩니다. 생성된 스텁은 가독성을 높이기 위해 다양한 설명에서 사용자에게 친숙한 이름을 사용합니다.

WSDL 작업에 대한 클라이언트 프록시

Wsutil.exe는 모든 작업에 대한 클라이언트 프록시를 생성합니다. 애플리케이션은 접두사 명령줄 옵션을 사용하여 메서드 서명을 덮어쓸 수 있습니다.

HRESULT WINAPI bindingName_SimpleMethod(WS_SERVICE_PROXY *serviceProxy,
  WS_HEAP *heap,
  int a,
  int *b,
  int *c,
  const WS_CALL_PROPERTY* callProperties,
  ULONG callPropertyCount,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR * error )
{
  void* argList[] = {&a, &b, &c};
  return WsCall(_serviceProxy,
    (WS_OPERATION_DESCRIPTION*)&example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.SimpleMethod,
    (void **)&_argList,
    callProperties,
    callPropertyCount,
    heap,
    asyncContext,
    error
  );      
}

작업 호출자는 유효한 매개 변수를 전달해야 합니다. 출력 매개 변수는 힙 매개 변수에 지정된 WS_HEAP 값을 사용하여 할당됩니다. 호출 함수는 모든 출력 매개 변수에 대한 메모리를 해제하도록 힙을 다시 설정하거나 해제할 수 있습니다. 작업이 실패하면 사용 가능한 경우 선택적 오류 개체에서 추가 세부 정보 오류 정보를 검색할 수 있습니다.

Wsutil.exe는 바인딩에 설명된 모든 작업에 대한 서비스 스텁을 생성합니다.

HRESULT CALLBACK ISimpleService_SimpleMethodStub(
  const WS_OPERATION_CONTEXT *context,
  void * stackStruct,
  void * callback,
  const WS_ASYNC_CONTEXT * asyncContext,
  WS_ERROR *error )
{
  SimpleMethodParamStruct *pstack = (SimpleMethodParamStruct *) stackstruct;
  SimpleMethodOperation operation = (SimpleMethodOperation)callback;
  return operation(context, pstack->a, &(pstack->b), &(pstack->c ), asyncContext, error );
}

위의 섹션에서는 스텁 파일에만 로컬로 모든 정의를 포함하는 로컬 구조의 프로토타입에 대해 설명합니다. 후속 섹션에서는 설명의 정의를 설명합니다.

WSDL 정의 생성

Wsutil.exe는 모든 로컬 전용 정의를 포함하는 *service_name*Local 형식의 *<<file_name>>*LocalDefinitions라는 상수 정적(const static) 구조체를 생성합니다.

const static _SimpleServiceLocal example_wsdlLocalDefinitions =
{
  {  // global types
  ...
  }, // global types
  {  // global elements
  ...
  }, // global elements
  {  // messages
  ...
  }, //messages
  ...
  {  // dictionary
  ...
  }, // dictionary
},

지원되는 WSDL 설명은 다음과 같습니다.

  • wsdl:service
  • wsdl:binding
  • wsdl:portType
  • wsdl:operation
  • wsdl:message

wsdl:operation 및 wsdl:message 처리

WSDL 문서에 지정된 각 작업은 Wsutil.exe에 의해 서비스 작업에 매핑됩니다. 이 도구는 서버와 클라이언트 모두에 대한 서비스 작업에 대한 별도의 정의를 생성합니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   <wsdl:input wsaw:Action="http://Example.org/ISimpleService/SimpleMethod" 
   message="tns:ISimpleService_SimpleMethod_InputMessage" />
   <wsdl:output wsaw:Action="http://Example.org/ISimpleService/SimpleMethodResponse" 
   message="tns:ISimpleService_SimpleMethod_OutputMessage" />
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
</wsdl:definitions>

입력 및 출력 메시지 데이터 요소의 레이아웃은 입력 및 출력 메시지가 연결된 결과 서비스 작업의 실제 서명과 함께 인프라에 대한 serialization 메타데이터를 생성하기 위해 도구에 의해 평가됩니다.

특정 portType 내의 각 작업에 대한 메타데이터에는 입력이 있고 필요에 따라 출력 메시지가 있으며, 이러한 각 메시지는 WS_MESSAGE_DESCRIPTION 매핑됩니다. 이 예제에서는 inputMessageDescription과 선택적으로 각각 WS_OPERATION_DESCRIPTION outputMessageDescription에 매핑된 portType의 작업에 대한 입력 및 출력 메시지입니다.

각 WSDL 메시지에 대해 도구는 아래와 같이 WS_ELEMENT_DESCRIPTION 정의를 참조하는 WS_MESSAGE_DESCRIPTION 생성합니다.

... 
{    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.DefaultBinding_ISimpleServiceISimpleService_SimpleMethod_InputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&(WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethodReponse
},  // message description for ISimpleService_SimpleMethod_InputMessage
...

메시지 설명은 입력 요소 설명을 참조합니다. 요소는 전역적으로 정의되므로 메시지 설명은 로컬 정적 요소 대신 전역 정의를 참조합니다. 마찬가지로 요소가 다른 파일에 정의된 경우 Wsutil.exe는 해당 파일에서 전역적으로 정의된 구조체에 대한 참조를 생성합니다. 예를 들어 SimpleMethodResponse가 다른 example.xsd 파일에 정의된 경우 Wsutil.exe는 다음을 대신 생성합니다.

...
{    // message description for ISimpleService_SimpleMethod_InputMessage
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.DefaultBinding_ISimpleServiceISimpleService_SimpleMethod_InputMessageactionName,
(WS_ELEMENT_DESCRIPTION*)&(WS_ELEMENT_DESCRIPTION*)&example_xsd.globalElements.SimpleMethodReponse
},  // message description for ISimpleService_SimpleMethod_InputMessage
...

각 메시지 설명에는 모든 메시지 데이터 요소에 대한 작업 및 특정 요소 설명(WS_ELEMENT_DESCRIPTION 형식 필드)이 포함됩니다. RPC 스타일 메시지 또는 여러 파트가 있는 메시지의 경우 추가 정보를 캡슐화하기 위해 래퍼 요소가 만들어집니다.

RPC 스타일 지원

Wsutil.exe는 SOAP 1.2 사양에 대한 WSDL 1.1 바인딩 확장에 따라 문서 스타일과 RPC 스타일 작업을 지원합니다. RPC 및 리터럴 스타일 작업은 WS_RPC_LITERAL_OPERATION 표시됩니다. 서비스 모델은 RPC/리터럴 작업에서 응답 본문 래퍼 요소의 이름을 무시합니다.

Wsutil.exe는 기본적으로 인코딩 스타일 작업을 지원하지 않습니다. WS_XML_BUFFER 매개 변수는 메시지를 인코딩하기 위해 생성되며 개발자는 불투명 버퍼를 직접 채워야 합니다.

여러 메시지 파트 지원

Wsutil.exe는 하나의 메시지에서 여러 메시지 파트를 지원합니다. 다음과 같이 여러 부분으로 구성된 메시지를 지정할 수 있습니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:message name="ISimpleService_MutipleParts_InputMessage">
  <wsdl:part name="part1" element="tns:SimpleElement1" />
  <wsdl:part name="part2" element="tns:SimpleElement2" />
 </wsdl:message>
</wsdl:definitions>

메시지에 여러 부분이 포함된 경우 Wsutil.exe는 메시지 요소에 대한 WS_STRUCT_TYPE 필드를 생성합니다. 문서 스타일을 사용하여 메시지를 나타내는 경우 Wsutil.exe는 구조체 형식의 래퍼 요소를 생성합니다. 래퍼 요소에는 이름이나 특정 네임스페이스가 없으며 래퍼 구조에는 모든 파트의 모든 요소가 필드로 포함됩니다. 래퍼 요소는 내부 전용이며 메시지 본문에서 serialize되지 않습니다.

메시지가 RPC 또는 리터럴 스타일 표현을 사용하는 경우 Wsutil.exe는 WSDL SOAP 확장 사양에 따라 작업 이름을 요소 이름으로, 지정된 네임스페이스를 서비스 네임스페이스로 사용하여 래퍼 요소를 만듭니다. 요소의 구조에는 메시지 파트에 지정된 형식을 나타내는 필드 배열이 포함됩니다. 래퍼 요소는 SOAP 사양에 표시된 대로 메시지 본문의 실제 상위 요소에 매핑됩니다.

서버 쪽에서 각 작업은 결과 서버 서비스 작업의 typedef를 생성합니다. 이 typedef는 앞에서 설명한 대로 함수 테이블의 작업을 참조하는 데 사용됩니다. 또한 모든 작업을 수행하면 실제 메서드에 대한 대리자를 대신하여 nfrastructure가 호출하는 스텁 함수가 생성됩니다.

typedef HRESULT (CALLBACK *SimpleMethodCallback) (
  const WS_OPERATION_CONTEXT* context,
  unsigned int  a,
  unsigned int * b,
  unsigned int * c,
  const WS_ASYNC_CONTEXT* asyncContext,
  WS_ERROR* error
  );

SimpleMethod 작업의 경우 SimpleMethodOperation typedef가 위에 정의되어 있습니다. 생성된 메서드에는 SimpleMethod 작업에 대한 입력 및 출력 메시지의 메시지 파트를 명명된 매개 변수로 사용하여 확장된 인수 목록이 있습니다.

클라이언트 쪽에서 각 작업은 프록시 서비스 작업에 매핑됩니다.

HRESULT WINAPI SimpleMethod (
  WS_SERVICE_PROXY* serviceProxy,
  ws_heap *heap,
  unsigned int  a,
  unsigned int * b,
  unsigned int * c,
  const WS_ASYNC_CONTEXT* asyncContext,
  WS_ERROR* error);

wsdl:binding 처리

WWSAPI 서비스 모델은SOAP 바인딩 확장을 지원합니다. 각 바인딩에 대해 연결된 portType이 있습니다.

비누 바인딩 확장에 지정된 전송은 권고 전용입니다. 애플리케이션은 채널을 만들 때 전송 정보를 제공해야 합니다. 현재 WS_HTTP_BINDING 및 WS_TCP_BINDING 바인딩을 지원합니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:binding name="DefaultBinding_ISimpleService" type="tns:ISimpleService">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="SimpleMethod">
   <soap:operation soapAction="http://Example.org/ISimpleService/SimpleMethod" 
   style="document" />
   <wsdl:input>
    <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
    <soap:body use="literal" />
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
</wsdl:definitions>

이 예제 WSDL 문서에서는 ISimpleService용 portType이 하나만 있습니다. 제공된 SOAP 바인딩은 WS_HTTP_BINDING 지정된 HTTP 전송을 나타냅니다. 이 구조체는 애플리케이션에서 사용할 수 있어야 하므로 정적 장식이 없습니다.

wsdl:portType 처리

WSDL의 각 portType 은 하나 이상의 작업으로 구성됩니다. 작업은 wsdl:binding에 표시된 SOAP 바인딩 확장과 일치해야 합니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:portType name="ISimpleService">
  <wsdl:operation name="SimpleMethod">
   ...
  </wsdl:operation>
 </wsdl:portType>
</wsdl:definitions>

이 예제에서 ISimpleService portType 에는 SimpleMethod 작업만 포함됩니다. 이는 SOAP 작업에 매핑되는 WSDL 작업이 하나만 있는 바인딩 섹션과 일치합니다.

ISimpleService portType 에는 SimpleMethod라는 하나의 작업만 있으므로 해당 함수 테이블에는 서비스 작업으로 SimpleMethod만 포함됩니다.

메타데이터 측면에서 각 portType은 Wsutil.exe에서 WS_CONTRACT_DESCRIPTION 매핑됩니다. portType 내의 각 작업은 WS_OPERATION_DESCRIPTION 매핑됩니다.

이 예제에서 portType 도구는 ISimpleService에 대한 WS_CONTRACT_DESCRIPTION 생성합니다. 이 계약 설명에는 ISimpleService portType에서 사용할 수 있는 특정 개수의 작업과 iSimpleService용 portType에 정의된 개별 작업을 나타내는 WS_OPERATION_DESCRIPTION 배열이 포함되어 있습니다. ISimpleService용 ISimpleService portType에는 하나의 작업만 있으므로 WS_OPERATION_DESCRIPTION 정의가 하나만 있습니다.

...  part of LocalDefinitions structure
{    // array of operations for DefaultBinding_ISimpleService
(WS_OPERATION_DESCRIPTION*)&example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.SimpleMethod,
},    // array of operations for DefaultBinding_ISimpleService
{    // contract description for DefaultBinding_ISimpleService
1,
(WS_OPERATION_DESCRIPTION**)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.operations,
WS_HTTP_CHANNEL_BINDING,
},  // end of contract description for DefaultBinding_ISimpleService
},    // DefaultBinding_ISimpleService       ...

wsdl:service 처리

WsUtil.exe는 서비스를 사용하여 바인딩/porttype을 찾고 형식, 메시지, 포트 형식 정의 등을 설명하는 계약 구조를 생성합니다. 계약 설명은 외부에서 액세스할 수 있으며 생성된 헤더를 통해 지정된 전역 정의 구조의 일부로 생성됩니다.

WsUtil.exe는 wsdl:port에 정의된 EndpointReference 확장을 지원합니다. 엔드포인트 참조는 서비스의 엔드포인트 정보를 설명하는 방법으로 WS-ADDRESSING에 정의됩니다. 일치하는 WS_ENDPOINT_ADDRESS_DESCRIPTION 함께 WS_XML_STRING 저장된 입력 엔드포인트 참조 확장 텍스트는 전역 구조의 endpointReferences 섹션에서 생성됩니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:service name="SimpleService">
  <wsdl:port name="ISimpleService" binding="tns:DefaultBinding_ISimpleService">
   <soap:address location="http://Example.org/ISimpleService" />
   <wsa:EndpointReference>
    <wsa:Address>http://example.org/wcfmetadata/WSHttpNon</wsa:Address>
   </wsa:EndpointReference> 
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>
  const _example_wsdl example_wsdl =
  {
  ... // global element description
  {// messages
  {    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_InputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethod,
},    // message description for ISimpleService_SimpleMethod_InputMessage
{    // message description for ISimpleService_SimpleMethod_OutputMessage
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_OutputMessageactionName,
  (WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethodResponse,
},    // message description for ISimpleService_SimpleMethod_OutputMessage
}, // messages
{// contracts
{   // DefaultBinding_ISimpleService
1,
(WS_OPERATION_DESCRIPTION**)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.operations,
WS_HTTP_CHANNEL_BINDING,
},    // end of DefaultBinding_ISimpleService
    }, // contracts
    {
        {
            {   // endpointAddressDescription
                WS_ADDRESSING_VERSION_0_9,
            },                    
            (WS_XML_STRING*)&xml_string_generated_in_stub // endpointReferenceString
        }, //DefaultBinding_ISimpleService
    }, // endpointReferences
}

WsUtil 생성 메타데이터를 사용하여 WS_ENDPOINT_ADDRESS 만들려면 다음을 수행합니다.

WsCreateReader      // Create a WS_XML_READER
Initialize a WS_XML_READER_BUFFER_INPUT
WsSetInput          // Set the encoding and input of the reader to generate endpointReferenceString
WsReadType        // Read WS_ENDPOINT_ADDRESS from the reader
    // Using WS_ELEMENT_TYPE_MAPPING, WS_ENDPOINT_ADDRESS_TYPE and generated endpointAddressDescription, 

클라이언트 프록시 또는 서비스 스텁의 상수 문자열은 WS_XML_STRING 형식의 필드로 생성되며 프록시 또는 스텁 파일의 모든 문자열에 대한 상수 사전이 있습니다. 사전의 각 문자열은 가독성을 높이기 위해 로컬 구조의 사전 부분에 필드로 생성됩니다.

... // dictionary part of LocalDefinitions structure
{    // xmlStrings
  { // xmlStrings
    WS_XML_STRING_DICTIONARY_VALUE("a",&example_wsdlLocalDefinitions.dictionary.dict, 0), 
    WS_XML_STRING_DICTIONARY_VALUE("http://Sapphire.org",&example_wsdlLocalDefinitions.dictionary.dict, 1), 
    WS_XML_STRING_DICTIONARY_VALUE("b",&example_wsdlLocalDefinitions.dictionary.dict, 2), 
    WS_XML_STRING_DICTIONARY_VALUE("SimpleMethod",&example_wsdlLocalDefinitions.dictionary.dict, 3),
    ...
  },  // end of xmlStrings
  {   // SimpleServicedictionary
    // 45026280-d5dc-4570-8195-4d66d13bfa34
    { 0x45026280, 0xd5dc, 0x4570, { 0x81, 0x95, 0x4d,0x66, 0xd1, 0x3b, 0xfa, 0x34 } },
    (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings,
    stringCount,
    TRUE,
  },
}
...

wsdl:type 처리

Wsutil.exe는 wsdl:type 사양의 XSD(XML 스키마) 문서만 지원합니다. 한 가지 특별한 경우는 메시지 포트가 전역 요소 정의를 지정하는 경우입니다. 이러한 경우에 사용되는 추론에 대한 자세한 내용은 다음 섹션을 참조하세요.

매개 변수 처리 추론

서비스 모델에서 WSDL 메시지는 메서드의 특정 매개 변수에 매핑됩니다. Wsutil.exe에는 두 가지 매개 변수 생성 스타일이 있습니다. 첫 번째 스타일에서는 작업에 입력 메시지에 대한 매개 변수 하나와 출력 메시지의 매개 변수 1개가 있습니다(필요한 경우). 두 번째 스타일에서 Wsutil.exe는 추론을 사용하여 입력 메시지와 출력 메시지 모두에 대한 구조체의 필드를 작업의 다른 매개 변수에 매핑하고 확장합니다. 이 두 번째 방법을 생성하려면 입력 메시지와 출력 메시지 모두 구조 형식 메시지 요소가 있어야 합니다.

Wsutil.exe는 입력 및 출력 메시지에서 작업 매개 변수를 생성할 때 다음 규칙을 사용합니다.

  • 여러 메시지 파트가 있는 입력 및 출력 메시지의 경우 각 메시지 부분은 매개 변수 이름으로 메시지 파트 이름을 사용하여 작업에서 별도의 매개 변수입니다.
  • 하나의 메시지 파트가 있는 RPC 스타일 메시지의 경우 메시지 부분은 매개 변수 이름으로 메시지 파트 이름을 사용하는 작업의 매개 변수입니다.
  • 하나의 메시지 파트가 있는 문서 스타일 입력 및 출력 메시지의 경우:
    • 메시지 파트의 이름이 "parameters"이고 요소 형식이 구조체인 경우 구조체의 각 필드는 필드 이름이 매개 변수 이름인 별도의 매개 변수로 처리됩니다.
    • 메시지 파트 이름이 "매개 변수"가 아닌 경우 메시지는 해당 매개 변수 이름으로 사용되는 메시지 이름을 사용하는 작업의 매개 변수입니다.
  • nillable 요소가 있는 문서 스타일 입력 및 출력 메시지의 경우 메시지는 매개 변수 이름으로 메시지 파트 이름을 사용하여 하나의 매개 변수에 매핑됩니다. 포인터가 NULL일 수 있음을 나타내기 위해 한 가지 추가 간접 참조 수준이 추가됩니다.
  • 필드가 입력 메시지 요소에만 표시되는 경우 필드는 [in] 매개 변수로 처리됩니다.
  • 필드가 출력 메시지 요소에만 표시되는 경우 필드는 [out] 매개 변수로 처리됩니다.
  • 입력 메시지와 출력 메시지 둘 다에 표시되는 이름과 형식이 같은 필드가 있는 경우 필드는 [in,out] 매개 변수로 처리됩니다.

매개 변수의 방향을 결정하는 데 사용되는 도구는 다음과 같습니다.

  • 필드가 입력 메시지 요소에만 표시되는 경우 필드는 매개 변수로만 처리됩니다.
  • 필드가 출력 메시지 요소에만 표시되는 경우 필드는 out 매개 변수로만 처리됩니다.
  • 입력 메시지와 출력 메시지 둘 다에 동일한 이름과 형식이 같은 필드가 있는 경우 필드는 in,out 매개 변수로 처리됩니다.

Wsutil.exe는 시퀀스된 요소만 지원합니다. Wsutil.exe가 in 매개 변수와 out 매개 변수를 단일 매개 변수 목록으로 결합할 수 없는 경우 [in,out] 매개 변수와 관련하여 잘못된 순서 지정을 거부합니다. 이름 충돌을 방지하기 위해 매개 변수 이름에 접미사를 추가할 수 있습니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethod" />
 </wsdl:message>
 <wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
  <wsdl:part name="parameters" element="tns:SimpleMethodResponse" />
 </wsdl:message>
</wsdl:definitions>

Wsutil.exe는 아래 매개 변수 정의에 표시된 것처럼 tns:SimpleMethod 및 tns:SimpleMethodResponse ato의 필드를 매개 변수로 간주합니다.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://Example.org" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" targetNamespace="http://Example.org" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
 <wsdl:types>
  <xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified" 
  targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:import namespace="http://Example.org" />
   <xs:element name="SimpleMethod">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="a" type="xs:unsignedInt" />
      <xs:element name="b" type="xs:unsignedInt" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="SimpleMethodResponse">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="b" type="xs:unsignedInt" />
      <xs:element name="c" type="xs:unsignedInt" />
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:schema>
 </wsdl:types>
</wsdl:definitions>

Wsutil.exe는 위 목록의 필드에서 매개 변수 목록을 확장하고 다음 코드 예제에서 ParamStruct 구조를 생성합니다. 서비스 모델 런타임은 이 구조를 사용하여 클라이언트 및 서버 스텁에 인수를 전달할 수 있습니다.

typedef struct SimpleMethodParamStruct {
  unsigned int   a;  
  unsigned int   b;
  unsigned int   c;
} ;

이 구조는 클라이언트 및 서버 쪽의 스택 프레임을 설명하는 데만 사용됩니다. 메시지 설명이나 메시지 설명에서 참조하는 요소 설명은 변경되지 않습니다.

  // following are local definitions for the complex type
  { // field description for a
  WS_ELEMENT_FIELD_MAPPING,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_INT32_TYPE,
  0,
  WsOffsetOf(_SimpleMethod, a),
  0,
  0,
  },    // end of field description for a
  { // field description for b
  WS_ELEMENT_FIELD_MAPPING,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.bLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_INT32_TYPE,
  0,
  WsOffsetOf(_SimpleMethod, b),
  0,
  0,
  },    // end of field description for b
  {    // fields description for _SimpleMethod
  (WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.a,
  (WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.b,
  },
  {  // structure definition
  sizeof(_SimpleMethod),
  __alignof(_SimpleMethod),
  (WS_FIELD_DESCRIPTION**)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs._SimpleMethodFields,
  WsCountOf(example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs._SimpleMethodFields),
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings._SimpleMethodTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  0,
  },   // struct description for _SimpleMethod
  // following are global definitions for the out parameter
  ...
  {  // element description
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings._SimpleMethodTypeName,
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
  WS_STRUCT_TYPE,
  (void *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod._SimpleMethoddescs.structDesc,
  },
  {    // message description for ISimpleService_SimpleMethod_InputMessage
  (WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.ISimpleService_SimpleMethod_InputMessageactionName,
(WS_ELEMENT_DESCRIPTION*)&example_wsdl.globalElements.SimpleMethod,
  },    // message description for ISimpleService_SimpleMethod_InputMessage

일반적으로 모든 [out] 및 [in,out] 매개 변수에 대해 한 수준의 간접 참조가 추가됩니다.

매개 변수 없는 작업

문서 및 리터럴 작업의 경우 Wsutil.exe는 다음과 같은 경우 하나의 입력 매개 변수와 하나의 출력 매개 변수가 있는 것으로 작업을 처리합니다.

  • 입력 또는 출력 메시지에는 둘 이상의 부분이 있습니다.
  • 메시지 부분은 하나뿐이며 메시지 파트 이름은 "매개 변수"가 아닙니다.

.. 위의 예제에서 메시지 파트의 이름이 ParamIn" 및 ParamOut이라고 가정하면 메서드 서명은 다음 코드가 됩니다.

typedef struct SimpleMethod{
unsigned int a;
unsigned int b;
};

typedef struct SimpleMethodResponse {
unsigned int b;
unsigned int c;
};

typedef  struct ISimpleService_SimpleMethodParamStruct
{
SimpleMethod  * SimpleMethod;
SimpleMethodResponse  * SimpleMethodResponse;
} ISimpleService_SimpleMethodParamStruct;

Wsutil.exe는 생성된 설명이 현재 플랫폼에 적용되는 경우 WsCall 및 서버 쪽 서비스 모델 엔진이 검사 수 있도록 작업 설명에 대한 버전 서명을 생성합니다.

이 버전 정보는 WS_OPERATION_DESCRIPTION 구조의 일부로 생성됩니다. 버전 번호는 구조체를 확장할 수 있도록 공용 구조체 암 선택기로 처리할 수 있습니다. 현재 versionID 는 후속 필드 없이 1로 설정됩니다. 나중에 versiosn은 버전 번호를 증가시키고 필요에 따라 더 많은 필드를 포함할 수 있습니다. 예를 들어 Wsutil.exe는 현재 버전 ID에 따라 다음 코드를 생성합니다.

{ // SimpleMethod
{ // parameter descriptions for SimpleMethod
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)0, (USHORT)-1 },
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)1, (USHORT)-1 },
{ WS_PARAMETER_TYPE_NORMAL, (USHORT)-1, (USHORT)1 },
},    // parameter descriptions for SimpleMethod
{    // operation description for SimpleMethod
1,
(WS_MESSAGE_DESCRIPTION*)&example_wsdl.messages.ISimpleService_SimpleMethod_InputMessage,
(WS_MESSAGE_DESCRIPTION*)&example_wsdl.messages.ISimpleService_SimpleMethod_OutputMessage,
3,
(WS_PARAMETER_DESCRIPTION*)example_wsdlLocalDefinitions.contracts.DefaultBinding_ISimpleService.SimpleMethod.params,
SimpleMethodOperationStub
}, //operation description for SimpleMethod
},  // SimpleMethod

나중에 다음과 같이 확장될 수 있습니다.

WS_OPERATION_DESCRIPTION simpleMethodOperationDesc =
{
  2,
  &ISimpleService_SimpleMethod_InputputMessageDesc,
  &ISimpleService_SimpleMethod_OutputMessageDesc,
  WsCountOf(SimpleMethodParameters),
  SimpleMethodParameters,
  ISimpleService_SimpleMethod_Stub,
  &forwardToString;   // just as an example.
};

보안

Wsutil 컴파일러 도구 항목의 보안 섹션을 참조하세요.