0

アンマネージ コードから 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 を参照する ac# コンソール アプリを使用して、そのサービスをホストします。また、サービスのエンドポイントを公開します。概して():

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++ コードからサービスにアクセスしたいからです。そのために、com 相互運用機能に登録し、実行中のホストのサービス参照も使用する .dll を使用します。

[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 "..\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;
}

... stringconcatinteropsvcclient.tli で次のような例外が発生します。

「xyz.exe の 0x75 で未処理の例外が発生しました: Microsoft C++ 例外: メモリ位置 0x で _com_error が発生しました...」

その後、続行して、strlen.asm で次の例外を取得できます。

「xyz.exe の 0x5d... (msvcr100d.dll) で未処理の例外: 0xC0...: アクセス違反の読み取り場所 0x00...」

この例外が停止した後。おそらく誰かがこの問題の解決策を持っているか、エラーがどこにあるのか考えています。簡単にするために、この例を使用します。私が取り組んでいるプロジェクトは、同じ構造を使用しています。また、wcf サービスも使用し、これらはアンマネージ C++ から呼び出されます。

4

2 に答える 2

1

小さなテスト プロジェクトを作成したところ、動作しています。

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:\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;
    }

私のアセンブリ名は ComTest.dll なので、次を使用して登録しました。

regasm Comtest.dll /CodeBase
于 2012-07-25T13:09:12.913 に答える
0

C++ コードでエラーが発生しました。CoCreateInstance(...) の誤った呼び出しです。助けてくれた zilog に感謝します。

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

また、serviceproxy の呼び出しにもエラーがありました。ベース アドレスにエンドポイント属性 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 サービスを呼び出すことができるようになりました。

于 2012-07-26T10:25:28.860 に答える