从非托管c++调用WCF服务导致访问冲突

Call to WCF-service from unmanaged c++ causes access violation

本文关键字:服务 访问冲突 WCF 调用 c++      更新时间:2023-10-16

我想从非托管代码访问wcf服务。服务只是连接到字符串并返回它们,以保持简单。

public class Stringconcat : IStringconcat
{
        public string stringconcat(string a, string b)
        {
            return b + a;
        }
}
[ServiceContract]
public interface IStringconcat
{
    [OperationContract]
    string stringconcat(string a, string b);
}

我用一个引用该服务的.dll的c#控制台应用程序托管该服务。并公开服务的端点。在主()中:

using (ServiceHost host = new ServiceHost(typeof(stringconcatservice.Stringconcat)))
{
    host.Open();
    Console.WriteLine("Press <ENTER> to terminate the host application");
    Console.ReadLine();
}

主机的配置如下:

<?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="serviceBehavior">
                        <serviceDebug includeExceptionDetailInFaults="true"/>
                        <serviceMetadata />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="serviceBehavior"
                name="stringconcatservice.Stringconcat" >
                    <endpoint address="stringconcat" binding="basicHttpBinding"
                    name="basicHttp" contract="stringconcatservice.IStringconcat" />
                    <endpoint binding="mexHttpBinding" name="mex"
                    contract="IMetadataExchange" />
                    <host>
                        <baseAddresses>
                         <add baseAddress="http://localhost:8000/stringconcatService" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
        </system.serviceModel>
    </configuration>

现在,如果我从一个.net客户端调用该服务,则一切都正常,该客户端使用该服务引用的基地址。

StringconcatClient proxy = new StringconcatClient();
string a = " string a ";
string b = " string b ";
string c = proxy.stringconcat(a, b);
Console.WriteLine(c);
Console.WriteLine("Press <ENTER> to terminate Client.");
Console.ReadKey();

现在来谈谈我的问题。因为我想从非托管c++代码访问该服务。为此,我使用了一个.dll,它注册com互操作,还使用运行主机的服务引用。

[Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
{
    public string stringconcat(string a, string b)
    {
        StringconcatClient client = new StringconcatClient();
        return client.stringconcat(a, b);
    }
}
[Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
[ComVisible(true)]
public interface IStringconcat_IAMCOM
{
    [DispId(1)]
    string stringconcat(string a, string b);
}

现在,当我尝试通过带有c++的中介.dll访问服务时。。。

#import "..stringconcatInteropSvcClientbinDebugstringconcatInteropSvcClient.tlb" 
#include <iostream>
#include <stdio.h>
using namespace stringconcatInteropSvcClient;
int main(int argc, const char* argv[])
{
    HRESULT hr = CoInitialize(NULL);
    BSTR a =  L" string a ";
    BSTR b =  L" string b ";
    IStringconcat_IAMCOM* q;
    hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER,
    __uuidof(IStringconcat_IAMCOM), (void**)&q );
    std::cout << q->stringconcat(a, b);
    //Uninitialize COM.
    CoUninitialize();
    return 0;
}

我在字符串oncatinteropsvcclient.tli中得到一个异常,比如:

"xyz.exe中0x75处的未命名异常:内存位置0x处的Microsoft C++异常:_com_error…"

然后我可以继续并在strlen.asm中获得下一个异常:

"xyz.exe:0xC0…中0x5d…(msvcr100d.dll)处的未命名异常:读取位置0x00时发生访问冲突…"

在该异常停止之后。也许有人对这个问题有一个解决方案,或者知道错误可能在哪里。我只是用这个例子来保持简单。我正在进行的项目使用相同的结构。它还使用wcf服务,这些服务将从非托管c++中调用。

刚刚创建了一个小型测试项目,它正在运行:

namespace ComTest
{
    [Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
    {
        public string stringconcat(string a, string b)
        {            
            return a + b;
        }
    }
    [Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IStringconcat_IAMCOM
    {
        [DispId(1)]
        string stringconcat(string a, string b);
    }
}

客户:

#import "C:UsersrstDocumentsVisual Studio 2008ProjectsComTestComTestbinDebugComTest.tlb" 
#include <iostream>
#include <stdio.h>
#include <windows.h>
using namespace ComTest;
    int main(int argc, const char* argv[])
    {
        HRESULT hr = CoInitialize(NULL);
        BSTR a =  L" string a ";
        BSTR b =  L" string b ";
        IStringconcat_IAMCOM* q;
        hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER,
        __uuidof(IStringconcat_IAMCOM), (void**)&q );
        std::cout << q->stringconcat(a, b);
        //Uninitialize COM.
        CoUninitialize();
        return 0;
    }

我的程序集名称是ComTest.dll,所以我使用注册了它

regasm Comtest.dll /CodeBase

我在c++代码中出现错误,CoCreateInstance(…)调用错误,感谢zilog的帮助。

IStringconcat_IAMCOM* q;
hr = CoCreateInstance(__uuidof(Stringconcat_IAMCOM), NULL, CLSCTX_INPROC_SERVER, __uuidof(IStringconcat_IAMCOM), (void**)&q );

在对serviceproxy的调用中也出现了错误。我不得不在基地址中添加endpoint属性address="stringconcat"。地址应该是这样的:

http://localhost:8000/stringconcatService/stringconcat

我现在用这种方式创建服务代理:

[Guid("E4435D3B-CBC3-4D41-B4A5-D8116B394195")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Stringconcat_IAMCOM : IStringconcat_IAMCOM
{
    public string stringconcat(string a, string b)
    {  
        EndpointAddress ep = new EndpointAddress("http://localhost:8000/stringconcatService/stringconcat");
        proxy = ChannelFactory<IStringconcat>.CreateChannel(new BasicHttpBinding(), ep);
        proxy.stringconcat(string a, string b);
    }
}
[Guid("E130F97E-1844-4C8B-9E57-AF42632A2557")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IStringconcat_IAMCOM
{
    [DispId(1)]
    string stringconcat(string a, string b);
}

现在我可以从c++调用WCF服务了,太棒了!