PInvoke - как представить поле из COM-интерфейса

StackOverflow https://stackoverflow.com/questions/1606530

  •  05-07-2019
  •  | 
  •  

Вопрос

Я ссылаюсь на структуру COM, которая начинается следующим образом:

[scriptable, uuid(ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e)]
interface nsICacheSession : nsISupports
{
    /**
     * Expired entries will be doomed or evicted if this attribute is set to
     * true.  If false, expired entries will be returned (useful for offline-
     * mode and clients, such as HTTP, that can update the valid lifetime of
     * cached content).  This attribute defaults to true.
     */
    attribute PRBool doomEntriesIfExpired;
...

Источник:http://dxr.proximity.on.ca/dxr/mozilla-central/netwerk/cache/public/nsICacheSession.idl.html#58

Я нашел код для импорта этого интерфейса в мое приложение на C #.Однако код, должно быть, неправильный, так как set метод не кажется полезным, а также выдает ошибку, когда я пытаюсь вызвать его, просто чтобы посмотреть, что произойдет:

[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
    [return: MarshalAs(UnmanagedType.Bool)]
    void set_doomEntriesIfExpired();
    [return: MarshalAs(UnmanagedType.Bool)]
    bool get_doomEntriesIfExpired();
...

Каков правильный способ установить значение doomEntriesIfExpired и как мне сослаться на это из моего кода?

Редактировать

Я изменил свой код на следующий, который выдал "System.AccessViolationException:Попытка чтения или записи защищенной памяти, бла-бла-бла...":

[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
    void set_doomEntriesIfExpired(bool enabled);
    bool get_doomEntriesIfExpired();
...
Это было полезно?

Решение

Ответ, который вы вставили, хорош.В COM-интерфейсе bools по умолчанию маршалируются как VARIANT_BOOL , поэтому ваше добавление атрибута MarshalAs для указания маршалеру использовать стандартный 4-байтовый тип BOOL является правильным, хотя для части получения уравнения также требуется добавление атрибута.

В общем, мне нравится оставлять свойства, определенные в интерфейсе, как свойства, а не разбивать их на их получатели и установщики.Он лучше соответствует семантике определения интерфейса и, как правило, также легче читается.Вы должны иметь возможность переписать свое определение импорта COM следующим образом, чтобы сохранить природу атрибута doomEntriesIfExpired:

[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{

    bool doomEntriesIfExpired 
    { 
        [param:MarshalAs(UnmanagedType.Bool)]set; 
        [return:MarshalAs(UnmanagedType.Bool)]get; 
    }

...

Другие советы

Тот факт, что вы заявляете о [return: MarshalAs(UnmanagedType.Bool)] для вашего void set метод, очевидно, является источником ошибок.

Тем не менее, мне удалось закодировать плагин mozilla на C ++ без тегов [return ...] в .idl, например:

[scriptable, uuid(ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e)]
interface nsICacheSession : nsISupports
{
    void set_doomEntriesIfExpired(in bool value);
    bool get_doomEntriesIfExpired();
}

Кстати, вы уверены, что можете закодировать плагин nsi на C #?

Оказывается, ответ был следующим:

[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
    void set_doomEntriesIfExpired([In, MarshalAs(UnmanagedType.Bool)] ref bool enabled);
    bool get_doomEntriesIfExpired();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top