首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何为非托管C ++客户端创建WCF服务?

如何为非托管C ++客户端创建WCF服务?
EN

Stack Overflow用户
提问于 2018-03-27 00:59:37
回答 2查看 0关注 0票数 0

我需要让非托管的Windows C ++客户端与WCF服务通话。C ++客户端可以在Win2000及更高版本上运行。我可以控制WCF服务和正在使用的C ++ API。由于它是专有应用程序,所以最好在可能的情况下使用Microsoft的东西,绝对不是GNU许可的API。那些有它工作的人,你能分享一步一步的过程如何使它工作?

到目前为止,我已经研究了以下选项:

  • WWSAPI - 不好,不适用于Win 2000客户端。
  • ATL Server,使用以下指南作为参考。我遵循了概述的步骤(删除策略引用并将WSDL扁平化),但是生成的WSDL仍然无法使用sproxy

还有什么想法?请仅在您自己确实有效时才回答。

我为任何我可能感到困惑的人道歉:我寻找的是从没有安装.NET框架的客户端调用WCF服务的方法,因此使用基于.NET的帮助程序库不是一种选择,它必须是纯粹的非托管C ++

EN

Stack Overflow用户

发布于 2018-03-27 10:49:05

对于那些有兴趣的人,我找到了一个半工作的ATL服务器解决方案。以下是主机代码,注意它使用的是BasicHttpBinding,它是唯一可以与ATL Server一起工作的代码:

代码语言:javascript
复制
        var svc =  new Service1();
        Uri uri = new Uri("http://localhost:8200/Service1");
        ServiceHost host = new ServiceHost(typeof(Service1), uri);

        var binding = new BasicHttpBinding();
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(IService1), binding, uri);
        endpoint.Behaviors.Add(new InlineXsdInWsdlBehavior());

        host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
        var mex = host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
        host.Open();

        Console.ReadLine();

InlineXsdInWsdlBehavior的代码可以在这里找到。需要对InlineXsdInWsdlBehavior进行一项重要更改,以便在涉及复杂类型时使用sproxy正常工作。它是由sproxy中的错误引起的,它没有正确地限定命名空间别名,所以wsdl不能有重复的命名空间别名,或者sproxy会被废弃。以下是需要改变的功能:

代码语言:javascript
复制
    public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
    {
        int tnsCount = 0;

        XmlSchemaSet schemaSet = exporter.GeneratedXmlSchemas;

        foreach (WsdlDescription wsdl in exporter.GeneratedWsdlDocuments)
        {
            //
            // Recursively find all schemas imported by this wsdl
            // and then add them. In the process, remove any
            // <xsd:imports/>
            //
            List<XmlSchema> importsList = new List<XmlSchema>();
            foreach (XmlSchema schema in wsdl.Types.Schemas)
            {
                AddImportedSchemas(schema, schemaSet, importsList, ref tnsCount);
            }
            wsdl.Types.Schemas.Clear();
            foreach (XmlSchema schema in importsList)
            {
                RemoveXsdImports(schema);
                wsdl.Types.Schemas.Add(schema);
            }
        }
    }


    private void AddImportedSchemas(XmlSchema schema, XmlSchemaSet schemaSet, List<XmlSchema> importsList, ref int tnsCount)
    {
        foreach (XmlSchemaImport import in schema.Includes)
        {
            ICollection realSchemas = schemaSet.Schemas(import.Namespace);
            foreach (XmlSchema ixsd in realSchemas)
            {
                if (!importsList.Contains(ixsd))
                {
                    var new_namespaces = new XmlSerializerNamespaces();
                    foreach (var ns in ixsd.Namespaces.ToArray())
                    {
                        var new_pfx = (ns.Name == "tns") ? string.Format("tns{0}", tnsCount++) : ns.Name;
                        new_namespaces.Add(new_pfx, ns.Namespace);
                    }

                    ixsd.Namespaces = new_namespaces;
                    importsList.Add(ixsd);
                    AddImportedSchemas(ixsd, schemaSet, importsList, ref tnsCount);
                }
            }
        }
    }

下一步是生成C ++头文件:

代码语言:javascript
复制
sproxy.exe /wsdl http://localhost:8200/Service1?wsdl

然后C ++程序看起来像这样:

代码语言:javascript
复制
using namespace Service1;

CoInitializeEx( NULL, COINIT_MULTITHREADED  );

{
    CService1T<CSoapWininetClient> cli;
    cli.SetUrl( _T("http://localhost:8200/Service1") );

    HRESULT hr = cli.HelloWorld(); //todo: analyze hr
}

CoUninitialize();
return 0;

最终的C ++代码处理复杂类型的方式相当不错,只是它不能将NULL分配给对象。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100003222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档