2009-10-22 76 views
1

我引用启动如下一个COM结构代表一个领域:的PInvoke - 如何从一个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; 
... 

Source: 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(); 
... 

回答

3

你插入的回答是好。在COM中,Interop bool默认被编组为VARIANT_BOOL,所以添加MarshalAs属性告诉编组使用标准的4字节BOOL类型是正确的,但方程的getter部分也需要添加属性。

一般来说,我喜欢将界面中定义的属性留作属性,而不是将它们分解为它们的getter和setter。它更好地匹配接口定义的语义,通常也更容易阅读。您应该能够重新写你的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; 
    } 

...

+0

不错,我没有意识到在使用互操作时你可以保留属性。 – 2009-10-27 07:22:55

1

事实上,你陈述了一个[return: MarshalAs(UnmanagedType.Bool)]为你的void set方法显然是一个错误的来源。

这么说,我不设法编写一个C++的Mozilla插件[返回...]标签中的.idl,如:

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

顺便说一句,你确定你可以编写一个NSI插件在C#中?

+0

我不是一个编码插件NSI,我延长GeckoFX( http://geckofx.org),以便我可以访问缓存中的项目 – 2009-10-22 11:56:43

+0

也就是说,上面的代码如何让我将该值设置为false?您所包含的设置方法不包括将其设置为的值... – 2009-10-22 11:58:50

+0

公平不够,我修复了setter(我刚刚复制了您的方法并错过了这一点) – Vinzz 2009-10-22 12:12:19

1

原来答案是以下几点:

[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();