Search code examples
c++cfirefox

why and how a head file is generated from the Interface Definition Language(IDL)


The following code is nsIEventTarget.h, which from firefox source library, but I am curious why and how this head file is generated from nsIEventTarget.idl ?

The Interface Definition Language

A file that contains interface and type library definitions is called an IDL file, and has a .idl file name extension. The Interface Definition Language (IDL) is not a programming language, but a descriptive language to describe the interfaces being implemented by objects. IDL files are similar to C++ header files.

The following code is nsIEventTarget.h. Even if I edit the following head file, it will recover and roll back to the original version after re-build.

nsIEventTarget.h

/*
 * DO NOT EDIT.  THIS FILE IS GENERATED FROM ../../../dist/idl/nsIEventTarget.idl
 */

#ifndef __gen_nsIEventTarget_h__
#define __gen_nsIEventTarget_h__


#ifndef __gen_nsISupports_h__
#include "nsISupports.h"
#endif

#ifndef __gen_nsIRunnable_h__
#include "nsIRunnable.h"
#endif

/* For IDL files that don't want to include root IDL files. */
#ifndef NS_NO_VTABLE
#define NS_NO_VTABLE
#endif
#include "nsCOMPtr.h"
#include "mozilla/AlreadyAddRefed.h"

/* starting interface:    nsIEventTarget */
#define NS_IEVENTTARGET_IID_STR "88145945-3278-424e-9f37-d874cbdd9f6f"

#define NS_IEVENTTARGET_IID \
  {0x88145945, 0x3278, 0x424e, \
    { 0x9f, 0x37, 0xd8, 0x74, 0xcb, 0xdd, 0x9f, 0x6f }}

class nsIEventTarget : public nsISupports {
 public:

  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEVENTTARGET_IID)

     nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
      return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
    }
  enum {
    DISPATCH_NORMAL = 0U,
    DISPATCH_SYNC = 1U,
    DISPATCH_AT_END = 2U
  };

  /* boolean isOnCurrentThread (); */
  NS_IMETHOD IsOnCurrentThread(bool *_retval) = 0;

  /* [binaryname(Dispatch),noscript] void dispatchFromC (in alreadyAddRefed_nsIRunnable event, in unsigned long flags); */
  NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags) = 0;

  /* [binaryname(DispatchFromScript)] void dispatch (in nsIRunnable event, in unsigned long flags); */
  NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) = 0;

  /* [noscript] void delayedDispatch (in alreadyAddRefed_nsIRunnable event, in unsigned long delay); */
  NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) = 0;

};

  NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventTarget, NS_IEVENTTARGET_IID)

/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSIEVENTTARGET \
  NS_IMETHOD IsOnCurrentThread(bool *_retval) override; \
  NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags) override; \
  NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override; \
  NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override; 

/* Use this macro when declaring the members of this interface when the
   class doesn't implement the interface. This is useful for forwarding. */
#define NS_DECL_NON_VIRTUAL_NSIEVENTTARGET \
  nsresult IsOnCurrentThread(bool *_retval); \
  nsresult Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags); \
  nsresult DispatchFromScript(nsIRunnable *event, uint32_t flags); \
  nsresult DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay); 

/* Use this macro to declare functions that forward the behavior of this interface to another object. */
#define NS_FORWARD_NSIEVENTTARGET(_to) \
  NS_IMETHOD IsOnCurrentThread(bool *_retval) override { return _to IsOnCurrentThread(_retval); } \
  NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags) override { return _to Dispatch(event, flags); } \
  NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override { return _to DispatchFromScript(event, flags); } \
  NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override { return _to DelayedDispatch(event, delay); } 

/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
#define NS_FORWARD_SAFE_NSIEVENTTARGET(_to) \
  NS_IMETHOD IsOnCurrentThread(bool *_retval) override { return !_to ? NS_ERROR_NULL_POINTER : _to->IsOnCurrentThread(_retval); } \
  NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags) override { return !_to ? NS_ERROR_NULL_POINTER : _to->Dispatch(event, flags); } \
  NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override { return !_to ? NS_ERROR_NULL_POINTER : _to->DispatchFromScript(event, flags); } \
  NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override { return !_to ? NS_ERROR_NULL_POINTER : _to->DelayedDispatch(event, delay); } 

#if 0
/* Use the code below as a template for the implementation class for this interface. */

/* Header file */
class nsEventTarget : public nsIEventTarget
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIEVENTTARGET

  nsEventTarget();

private:
  ~nsEventTarget();

protected:
  /* additional members */
};

/* Implementation file */
NS_IMPL_ISUPPORTS(nsEventTarget, nsIEventTarget)

nsEventTarget::nsEventTarget()
{
  /* member initializers and constructor code */
}

nsEventTarget::~nsEventTarget()
{
  /* destructor code */
}

/* boolean isOnCurrentThread (); */
NS_IMETHODIMP nsEventTarget::IsOnCurrentThread(bool *_retval)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* [binaryname(Dispatch),noscript] void dispatchFromC (in alreadyAddRefed_nsIRunnable event, in unsigned long flags); */
NS_IMETHODIMP nsEventTarget::Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* [binaryname(DispatchFromScript)] void dispatch (in nsIRunnable event, in unsigned long flags); */
NS_IMETHODIMP nsEventTarget::DispatchFromScript(nsIRunnable *event, uint32_t flags)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* [noscript] void delayedDispatch (in alreadyAddRefed_nsIRunnable event, in unsigned long delay); */
NS_IMETHODIMP nsEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* End of implementation class template. */
#endif

// convenient aliases:
#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
#define NS_DISPATCH_SYNC   nsIEventTarget::DISPATCH_SYNC
#define NS_DISPATCH_AT_END nsIEventTarget::DISPATCH_AT_END

#endif /* __gen_nsIEventTarget_h__ */

nsIEventTarget.idl

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISupports.idl"
#include "nsIRunnable.idl"
%{C++
#include "nsCOMPtr.h"
#include "mozilla/AlreadyAddRefed.h"
%}

native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>);

[scriptable, uuid(88145945-3278-424e-9f37-d874cbdd9f6f)]
interface nsIEventTarget : nsISupports
{
  /* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
%{C++
    nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
      return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
    }
%}

  /**
   * This flag specifies the default mode of event dispatch, whereby the event
   * is simply queued for later processing.  When this flag is specified,
   * dispatch returns immediately after the event is queued.
   */
  const unsigned long DISPATCH_NORMAL = 0;

  /**
   * This flag specifies the synchronous mode of event dispatch, in which the
   * dispatch method does not return until the event has been processed.
   *
   * NOTE: passing this flag to dispatch may have the side-effect of causing
   * other events on the current thread to be processed while waiting for the
   * given event to be processed.
   */
  const unsigned long DISPATCH_SYNC = 1;

  /**
   * This flag specifies that the dispatch is occurring from a running event
   * that was dispatched to the same event target, and that event is about to
   * finish.
   *
   * A thread pool can use this as an optimization hint to not spin up
   * another thread, since the current thread is about to become idle.
   *
   * These events are always async.
   */
  const unsigned long DISPATCH_AT_END = 2;

  /**
   * Check to see if this event target is associated with the current thread.
   *
   * @returns
   *   A boolean value that if "true" indicates that events dispatched to this
   *   event target will run on the current thread (i.e., the thread calling
   *   this method).
   */
  boolean isOnCurrentThread();

  /**
   * Dispatch an event to this event target.  This function may be called from
   * any thread, and it may be called re-entrantly.
   *
   * @param event
   *   The alreadyAddRefed<> event to dispatch.
   *   NOTE that the event will be leaked if it fails to dispatch.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [noscript, binaryname(Dispatch)] void dispatchFromC(in alreadyAddRefed_nsIRunnable event, in unsigned long flags);
  /**
   * Version of Dispatch to expose to JS, which doesn't require an alreadyAddRefed<>
   * (it will be converted to that internally)
   *
   * @param event
   *   The (raw) event to dispatch.
   * @param flags
   *   The flags modifying event dispatch.  The flags are described in detail
   *   below.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched.
   */
  [binaryname(DispatchFromScript)] void dispatch(in nsIRunnable event, in unsigned long flags);
  /**
   * Dispatch an event to this event target, but do not run it before delay
   * milliseconds have passed.  This function may be called from any thread.
   *
   * @param event
   *   The alreadyAddrefed<> event to dispatch.
   * @param delay
   *   The delay (in ms) before running the event.  If event does not rise to
   *   the top of the event queue before the delay has passed, it will be set
   *   aside to execute once the delay has passed.  Otherwise, it will be
   *   executed immediately.
   *
   * @throws NS_ERROR_INVALID_ARG
   *   Indicates that event is null.
   * @throws NS_ERROR_UNEXPECTED
   *   Indicates that the thread is shutting down and has finished processing
   * events, so this event would never run and has not been dispatched, or
   * that delay is zero.
   */
  [noscript] void delayedDispatch(in alreadyAddRefed_nsIRunnable event, in unsigned long delay);
};

%{C++
// convenient aliases:
#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
#define NS_DISPATCH_SYNC   nsIEventTarget::DISPATCH_SYNC
#define NS_DISPATCH_AT_END nsIEventTarget::DISPATCH_AT_END
%}

Solution

  • After compiling an .idl file the respective header file is generated along with few c files.

    So here in your case whenever you compile nsIEventTarget.idl, the nsIEventTarget.h is always regenerated.

    So your changes are disappearing.

    A COM object, when built, creates an IDL file. Then MIDL compiler parses this IDL to generate the type library(.tlb), header file (in your case) and some proxy files. The ".tlb" again serves the applications that want to consume the COM object from which the ".tlb" is generated.

    You do not need to know much about MIDL compiler. The IDE (eg: Visual Studio) will take care of all these actions. But still if you want to know more about it, you can refer to the link below:

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa367300(v=vs.85).aspx