简体   繁体   English

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

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

I want to access a wcf-service from unmanaged code. 我想从非托管代码访问wcf服务。 The service just concats to strings and returns them, to keep things simple. 该服务只是连接字符串并返回它们,以使事情保持简单。

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);
}

I host that service, with ac# console app that references the .dll of the service. 我使用引用该服务的.dll的ac#控制台应用程序托管该服务。 And exposes the endpoint for the service. 并公开服务的端点。 In the Main(): 在Main()中:

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

The config of the host looks like this: 主机的配置如下所示:

<?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>

Now everything works if I call the service from a .net client that uses for the service reference the base address. 现在,如果我从用于服务引用的.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();

Now to the problem I have. 现在我有问题了。 Because I want to access the service from unmanaged c++ code. 因为我想从非托管C ++代码访问服务。 For that i use a .dll, that registers for com interop and also uses the service reference of the running host. 为此,我使用一个.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);
}

Now when i try to access the service over the intermediary .dll whith c++... 现在,当我尝试通过中介.dll和C ++访问服务时...

#import "..\stringconcatInteropSvcClient\bin\Debug\stringconcatInteropSvcClient.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;
}

... I get an exception in stringconcatinteropsvcclient.tli like: ...我在stringconcatinteropsvcclient.tli中遇到异常,如下所示:

"Unhandeled exception at 0x75... in xyz.exe: Microsoft C++ exception: _com_error at memory location 0x..." “ xyz.exe中在0x75处发生未经处理的异常:Microsoft C ++异常:内存位置0x处出现_com_error ...”

then I can continue and get the next exception in strlen.asm: 然后我可以继续并在strlen.asm中获取下一个异常:

"Unhandeled exception at 0x5d... (msvcr100d.dll) in xyz.exe: 0xC0...: Access violation reading location 0x00..." “ xyz.exe中的0x5d ...(msvcr100d.dll)发生未经处理的异常:0xC0 ...:访问冲突读取位置0x00 ...”

after this exception stops. 此异常停止后。 Maybe somebody has an solution for this problem or an idea where the error could be. 也许有人对这个问题有解决方案,或者对错误可能出在哪里有了想法。 I just use this example to keep it simple. 我只是用这个例子来保持简单。 The project I am working on uses the same structure. 我正在从事的项目使用相同的结构。 It also uses wcf services and these will be called from unmanaged c++. 它还使用wcf服务,这些服务将从非托管c ++中调用。

Just created small test project, it is working: 刚刚创建了一个小型测试项目,它正在工作:

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);
    }
}

And client: 和客户:

#import "C:\Users\rst\Documents\Visual Studio 2008\Projects\ComTest\ComTest\bin\Debug\ComTest.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;
    }

My assembly name is ComTest.dll so i registered it using: 我的程序集名称是ComTest.dll,所以我使用以下方式注册了它:

regasm Comtest.dll /CodeBase

I had an error in the c++ code, false call of CoCreateInstance(...), thank you zilog for the help. 我的c ++代码有错误,CoCreateInstance(...)的错误调用,谢谢zilog的帮助。

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

And there was also an error in the the call for the serviceproxy. 并且在对serviceproxy的调用中也存在错误。 I had to add to the base address the endpoint attribute address="stringconcat". 我必须将端点属性address =“ stringconcat”添加到基本地址。 The address should have been like this: 地址应该是这样的:

http://localhost:8000/stringconcatService/stringconcat

And I create the service proxy now this way: 现在,我以这种方式创建服务代理:

[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);
}

Now i can make calls from c++ to WCF-Services, thats great! 现在,我可以从C ++调用WCF服务了,那就太好了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM