Ошибка компилятора C3646 «неизвестный спецификатор переопределения» в автоматически созданном .tlh при использовании importlib в idl

Я использую Visual Studio 2015, и у меня есть проект приложения C #, который определяет COM-интерфейс и генерирует файл .tlb при компиляции. Теперь я хочу импортировать этот Csharp.tlb в idl.

MyLibrary.idl:

import "oaidl.idl";
import "ocidl.idl";
import "Cplusplus.idl";

library MyLibrary
{
  importlib("stdole32.tlb");
  importlib("stdole2.tlb");
  importlib("Csharp.tlb");

  interface IMyCOM : IDispatch
  {
    [propget, id(1)]
    HRESULT CpluplusObject
    (
      [out,retval] ICplusplusObject** cplusplusObject
    );

    [propget, id(2)]
    HRESULT CsharpObject
    (
      [out, retval] ICsharpObject** csharpObject
    );
  }

  coclass MyCOM
  {
    [default] interface IMyCOM;
  };
}

Во время компиляции выдает ошибку

C3646 'csharpObject': неизвестный спецификатор переопределения в MyLibrary.tlh

MyLibrary.tlh был автоматически сгенерирован компиляцией и выглядит следующим образом

MyLibrary.tlh:

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

namespace MyLibrary {

  struct __declspec(uuid("8e664998-bc93-48e7-adcc-84fc8598cd5d"))
  /* dual interface */ ICplusplusObject;

  _COM_SMARTPTR_TYPEDEF(ICplusplusObject, __uuidof(ICplusplusObject));

  struct __declspec(uuid("388ebf11-05c8-4b86-b2bd-60f0ef38695e"))
  IMyLibrary : IDispatch
  {
    __declspec(property(get=GetCplusplusObject))
    ICplusplusObjectPtr cplusplusObject;
    __declspec(property(get=GetCsharpObject))
    ICsharpObjectPtr csharpObject;

    ICplusplusObjectPtr GetCplusplusObject ( );
    ICsharpObjectPtr GetCsharpObject ( );

    virtual HRESULT __stdcall get_CplusplusObject (
      /*[out,retval]*/ struct ICplusplusObject * * cplusplusObject ) = 0;
    virtual HRESULT __stdcall get_CsharpObject (
      /*[out,retval]*/ struct ICsharpObject * * csharpObject ) = 0;
  }

  __declspec(implementation_key(1)) ICplusplusObjectPtr IMyLibrary::GetcplusplusObject ( );
  __declspec(implementation_key(2)) ICsharpObjectPtr IMyLibrary::GetcsharpObject ( );
}

Ошибка означает, что ICsharpObjectPtr или ICsharpObject соответственно неизвестны, что я пока понимаю. ICplusplusObjectPtr известен, потому что import «ICplusplus.idl» добавил определения в .tlh и importlib («ICsharp.tlb»); не сделал очевидно.

По причинам тестирования я сгенерировал ICsharp.idl из .tlb с помощью OLE / COM Object Viewer и импортировал этот idl. После этого ошибка исчезла.

Но почему importlib для .tlb не работает напрямую? Я не хочу каждый раз генерировать файл idl из .tlb.

Я думаю, что отсутствует #include "ICsharp.tlh" или что-то еще, чтобы сделать этот тип известным для .tlh. Но как указать idl или компилятору правильно ссылаться на ICsharpObject?

Заранее большое спасибо за вашу помощь.


person MaLe    schedule 11.08.2016    source источник
comment
Вы определяете методы в середине блока library. В этом нет никакого смысла. Естественно, что методы должны быть частью интерфейса.   -  person Igor Tandetnik    schedule 12.08.2016
comment
Вы хотите использовать атрибут auto_search со своей директивой #import. Или сначала явно #import Csharp.tlb.   -  person Igor Tandetnik    schedule 12.08.2016
comment
Я исправил код MyLibrary.idl. Просто забыл прописать интерфейс, как вы уже заметили. Спасибо.   -  person MaLe    schedule 12.08.2016
comment
Оператор #import можно использовать в файле cpp, верно? Но я хочу импортировать .tlb в файл .idl, а не в файл .cpp. Я сделал это с помощью оператора importlib (Csharp.tlb), который приводит к этой ошибке. Если я сгенерировал Csharp.idl из этого файла Csharp.tlb, я смог использовать оператор import Csharp.idl, и он сработал. Но я не хочу, чтобы это преобразование .tld - ›. Idl.   -  person MaLe    schedule 12.08.2016
comment
Откуда взялся файл .tlh? Обычно это результат выражения #import в вашем коде C ++. Вы хотите сказать, что у вас нет такого заявления? При всем уважении, мне трудно поверить.   -  person Igor Tandetnik    schedule 12.08.2016
comment
Если вы запутались сейчас, то позже все будет гораздо сложнее. Возможно, вы слишком стараетесь сделать его похожим на единый API, хотя на самом деле это не так. Это также сложно для программиста-клиента, он должен ссылаться на обе библиотеки типов без каких-либо указаний на то, что это необходимо. И установка грубая, две разные DLL с очень разными процедурами регистрации. А строительство - дело грубое, изменение одного требует перестройки другого. Все это невозможно, однако гораздо легче разгадать их, если держать их по отдельности.   -  person Hans Passant    schedule 12.08.2016
comment
К сожалению, по большей части это устаревший код. Все, что я хочу сделать, это добавить еще один новый проект, написанный на C #. Все остальные написаны на C ++. Так что я думаю, что у меня действительно нет выбора, если я не хочу порвать с существующим интерфейсом. @IgorTandetnik: Да, вы абсолютно правы, у меня есть заявления #Import. Теперь я немного запутался во всех этих импортных вещах. Простите за это. Я просто думал о простом импорте. Ах, хорошо, моя проблема, похоже, связана с порядком #imports, которые генерируют .tlh. Я попробую это. Большое Вам спасибо.   -  person MaLe    schedule 13.08.2016


Ответы (1)


Это ошибка из-за неправильного порядка tlb-импорта. Директива #import пытается сгенерировать первичный (.tlh) и вторичный (.tli) файлы заголовков при компиляции. Если tlb использует тип другой библиотеки типов, которая не была импортирована первой, возникнет эта ошибка. В этом случае ошибка была решена следующим образом:

Importer.cpp

#import "CplusplusLibrary.tlb"
#import "CsharpLibrary.tlb"
#import "MyLibrary.tlb"

Спасибо большое, Игорь.

person MaLe    schedule 15.08.2016