c++ - 为什么以及如何从接口(interface)定义语言 (IDL) 生成头文件

标签 c++ c firefox

下面的代码是nsIEventTarget.h ,它来自 firefox 源库,但我很好奇为什么以及如何从 nsIEventTarget.idl 生成这个头文件?

接口(interface)定义语言

包含接口(interface)和类型库定义的文件称为 IDL 文件,文件扩展名为 .idl。接口(interface)定义语言(IDL)不是一种编程语言,而是一种描述性语言,用于描述对象所实现的接口(interface)。 IDL 文件类似于 C++ 头文件。

下面的代码是nsIEventTarget.h。即使我编辑下面的头文件,它也会在重新构建后恢复并回滚到原来的版本。

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
%}

最佳答案

编译 .idl 文件后,相应的头文件与几个 c 文件一起生成。

所以在你的例子中,当你编译 nsIEventTarget.idl 时,nsIEventTarget.h 总是被重新生成。

因此您的更改正在消失。

构建时创建 IDL 文件的 COM 对象。 然后 MIDL 编译器解析此 IDL 以生成类型库(.tlb)、头文件(在您的情况下)和一些代理文件。“.tlb”再次为想要使用的应用程序提供服务生成“.tlb”的 COM 对象。

您不需要对 MIDL 编译器了解太多。 IDE(例如:visual studio)将负责所有这些操作。但是,如果您想了解更多信息,可以引用以下链接:

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

关于c++ - 为什么以及如何从接口(interface)定义语言 (IDL) 生成头文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43164207/

相关文章:

c++ - 将其 move 到 map 后访问一对

c - 如何在C中操作全局变量

javascript - 页面生命周期 API - 是否可以手动卡住页面

css - 由于在背景元素上设置了透明度,Firefox 无法正确呈现背景颜色

javascript - 如何检测用户是否在 Firefox 42+ 中使用跟踪保护

c++ - 不能用大括号传递两次指针

c++ - 如何清除异常掩码

c++ - 为什么从函数返回时需要将数组声明为静态数组。 (C++)

c - 如何在C中打印如下图案?

c - 回溯队列