Получение COM-интерфейсов в.NET

Если это может быть полезно, я получил ОК, пригодный для смещенного по X уравнения мощности "R = a * numpy.power ((Mb), c)" с параметрами a = 3.3867896329655980E + 02, b = -5.0677344974815763E-01 и c = -1.0081095967950331E + 00, получая RMSE = 0.2558 и R-квадрат = 0.999997 plot

6
задан Ryan Gates 21 March 2014 в 13:38
поделиться

2 ответа

Это могла быть проблема с именем IServiceProvider. Проверьте, что Вы уже не импортировали интерфейс с тем же именем.

Когда я создаю библиотеку COM Interface с помощью IDL и затем пытаюсь импортировать его от другого клиента, я получаю предупреждение:

Warning 65  warning C4192: automatically excluding 'IServiceProvider' while importing type library 'ServiceLibrary.dll'

Иначе можно попытаться переименовать его к IServiceProvider2. Это - то, что я сделал, и все хорошо работает. Я использую Visual Studio 2008.

Если этот код работает правильно на Вашей машине (это работает отлично над моей), затем, проблема могла быть в Вашей реализации.

IDL:

import "oaidl.idl";

[
    object,
    uuid(9219CC5B-31CC-4868-A1DE-E18300F73C43),
    dual,
    nonextensible,
    helpstring("IService Interface"),
    pointer_default(unique)
]
interface IService : IDispatch
{
  HRESULT DoSomething(void);
}

[
    object,
    uuid(9219CC5B-31CC-4868-A1DE-E18300F73C44),
    dual,
    nonextensible,
    helpstring("IProvider Interface"),
    pointer_default(unique)
]
interface IServiceProvider2 : IDispatch
{
  HRESULT Init( IDispatch *sink, VARIANT_BOOL * result );
  HRESULT GetService( LONG serviceIndicator, IService ** result );
};

[
    uuid(9219CC5B-31CC-4868-A1DE-E18300F73C45),
    version(1.0),
]
library ServiceLibrary
{
    importlib("stdole2.tlb");

    interface IService;
    interface IServiceProvider2;
};

C#:

using System.Runtime.InteropServices;
using System.Windows.Forms;
using ServiceLibrary;
using IServiceProvider=ServiceLibrary.IServiceProvider2;

namespace COMInterfaceTester
{
    [ComVisible(true)]
    [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B2")]
    public interface INewService : IService
    {
        string ServiceName { get; }
    }

    [ComVisible(true)]
    [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B3")]
    public class NewService : INewService
    {
        public string _name;

        public NewService(string name)
        {
            _name = name;
        }

        //  implement interface
        #region IService Members

        public void DoSomething()
        {
            MessageBox.Show("NewService.DoSomething");
        }

        #endregion

        public string ServiceName
        {
            get { return _name; }
        }
    }

    [ComVisible(true)]
    [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B4")]
    public interface INewProvider : IServiceProvider
    {
        //  adds nothing, just implements
    }

    [ComVisible(true)]
    [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B5")]
    public class NewProvider : INewProvider
    {
        //  implement interface
        public void Init(object sink, ref bool result)
        {
            MessageBox.Show("NewProvider.Init");
        }

        public void GetService(int serviceIndicator, ref IService result)
        {
            result = new NewService("FooBar");
            MessageBox.Show("NewProvider.GetService");
        }
    }
}    

Клиент C++:

#include "stdafx.h"
#include <iostream>
#include <atlbase.h>
#import "COMInterfaceTester.tlb" raw_interfaces_only
#import "ServiceLibrary.dll" raw_interfaces_only

using std::cout;

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);   //Initialize all COM Components
    COMInterfaceTester::INewProviderPtr pNewProvider(__uuidof(COMInterfaceTester::NewProvider));
    ServiceLibrary::IServiceProvider2 *pNewProviderPtr;

    HRESULT hr = pNewProvider.QueryInterface(__uuidof(ServiceLibrary::IServiceProvider2), (void**)&pNewProviderPtr);

    if(SUCCEEDED(hr))
    {       
        VARIANT_BOOL result = VARIANT_FALSE;
        int *p = NULL;

        hr = pNewProviderPtr->Init((IDispatch*)p, &result);

        if (FAILED(hr))
        {
            cout << "Failed to call Init";
        }

        ServiceLibrary::IService *pService = NULL;
        hr = pNewProviderPtr->GetService(0, &pService);

        if (FAILED(hr))
        {
            cout << "Failed to call GetService";
        }
        else
        {
            COMInterfaceTester::INewService* pNewService = NULL;
            hr = pService->QueryInterface(__uuidof(COMInterfaceTester::INewService), (void**)&pNewService);

            if (SUCCEEDED(hr))
            {
                CComBSTR serviceName;
                pNewService->get_ServiceName(&serviceName); 

                if (serviceName == "FooBar")
                {
                    pService->DoSomething();
                }
                else
                    cout << "Unexpected service";

                pNewService->Release();

            }

            pService->Release();
        }

        pNewProviderPtr->Release();
    }
    else
        cout << "Failed to query for IServiceProvider2";

    pNewProvider.Release();
    CoUninitialize ();   //DeInitialize all COM Components

}
6
ответ дан 17 December 2019 в 00:16
поделиться

Вам, вероятно, придется указать дополнительные атрибуты на Вашем классе, чтобы иметь его маршал правильно. Я просмотрел бы доступные атрибуты здесь и возможно посмотрел бы на это учебное руководство, если Вы так уже не сделали.

1
ответ дан 17 December 2019 в 00:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: