tags:

views:

127

answers:

3

I am referencing a COM structure that starts as follows:

[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

I found code for importing that interface into my C# app. The code must be wrong though, as the set method doesn't seem to be useful and also throws an error when I try to call it just to see what happens:

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

What is the correct way to set the value of doomEntriesIfExpired and how do I reference this from my code?

EDIT

I changed my code to the following, which yielded "System.AccessViolationException: Attempt to read or write protected memory yada yada...":

[Guid("ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheSession
{
    void set_doomEntriesIfExpired(bool enabled);
    bool get_doomEntriesIfExpired();
...
+1  A: 

The fact that you state a [return: MarshalAs(UnmanagedType.Bool)] for your void set method is obviously a source of error.

That said, I managed to code a C++ mozilla plugin without the [return ...] tags in the .idl, eg:

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

By the way, are you sure you can code a nsi plugin in C# ?

Vinzz
I'm not coding an NSI plugin, I'm extending GeckoFX (http://geckofx.org) so that I can access items in the cache
Nathan Ridley
That said, how does your code above allow me to set the value to false? The set method you included doesn't include the value to set it to...
Nathan Ridley
fair enough, I fixed the setter (I just copied your method and missed this point)
Vinzz
Didn't know this geckofx project, which is obviously coded in C#
Vinzz
I've updated my code above. An exception is thrown.
Nathan Ridley
did you put the 'in' keyword?
Vinzz
Cheers, see below.
Nathan Ridley
glad it led you to the answer.
Vinzz
+1  A: 

Turns out the answer was the following:

[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();
Nathan Ridley
+1  A: 

The answer you inserted is good. In COM Interop bools are marshaled as VARIANT_BOOL by default so your addition of the MarshalAs attribute to tell the marshaler to use a standard 4 byte BOOL type is correct, though the getter part of the equation needs the attribute added as well.

In general, I like to leave properties defined in the interface as properties rather than breaking them out into their getters and setters. It matches the semantics of the interface definition better and is usually easier to read as well. You should be able to re-write your COM import definition as follows to retain the attribute nature of 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; 
    }

...

Stephen Martin
Nice, I didn't realise that you could retain properties when using interop.
Nathan Ridley