Как правильно передать параметры из VBScript в интерфейс COM, реализованный в C #? - PullRequest
2 голосов
/ 07 июня 2010

Я пытаюсь представить довольно простой класс C # для COM, который должен использоваться из VBScript (среди прочих). Некоторые объекты необходимо создавать с помощью COM-вызовов и позже они будут использоваться в последующих вызовах. Определение доступных классов и интерфейсов выглядит следующим образом:

namespace Test 
{
  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IComInterface
  {
      IFoo CreateFoo();
      void UseFoo(int x, IFoo f);
  }

  [ClassInterface(ClassInterfaceType.None)]
  public sealed class CComInterface : IComInterface
  {
      public CComInterface() {}
      public IFoo CreateFoo() { return new Foo(); }
      public void UseFoo(int x, IFoo f) { f.Bar(); }
  }

  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IFoo
  {
      void Bar();
  }

  [ClassInterface(ClassInterfaceType.None)]
  public class Foo : IFoo
  {
      internal Foo() {}
      public void Bar() {}
  } 
}

Самый простой мыслимый COM-клиент в VBScript делает это:

Dim ci
Set ci = WScript.CreateObject("Test.CComInterface")
Dim foo
Set foo = ci.CreateFoo
foo.Bar
ci.UseFoo 0, foo

В то время как вызов Bar завершается успешно, вызов UseFoo завершается с ошибкой «Ошибка 5: неверный вызов процедуры или неверный аргумент»

Сгенерированный IDL мне кажется нормальным:

dispinterface IComInterface {
    properties:
    methods:
        [id(0x60020003)]
        IFoo* CreateFoo();
        [id(0x60020004)]
        void UseFoo(
                        [in] long x, 
                        [in] IFoo* f);
};

Вызов vbs завершается успешно, когда я заключаю в скобки второй параметр следующим образом:

ci.UseFoo 0, (foo)

Насколько я понимаю (однако я не эксперт по VBScript), это заставляет ссылку на foo передаваться по значению, т. Е. Создается копия ссылки.

Как я могу изменить интерфейс так, чтобы он мог вызываться напрямую с помощью ссылки на foo? Так как это будет общедоступный интерфейс, используемый клиентами, мне не нравится идея объяснения, почему все созданные объекты должны быть возвращены в дополнительной паре скобок ...

Ответы [ 2 ]

2 голосов
/ 09 июня 2010

Louis.fr на MSDN Social помог мне - хитрость заключается в том, чтобы сказать маршаллеру, как маршалировать параметр следующим образом:

public void UseFoo(int x, [MarshalAs(UnmanagedType.IDispatch)] IFoo f) { f.Bar(); }
1 голос
/ 07 июня 2010

Попробуйте изменить интерфейс C # на параметр ref.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...