当前位置: 首页 > article >正文

Chromium Mojo(IPC)进程通信演示 c++(2)

122版本自带的mojom通信例子associated-interface 仅供学习参考:

codelabs\mojo_examples\02-associated-interface-freezing

一、目录结构如图:

二、interface.mojom接口

1、codelabs\mojo_examples\mojom\interface.mojom

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module codelabs.mojom;

// Bound in the renderer process; only used in
// `02-associated-interface-freezing` and
// `03-channel-associated-interface-freezing`.
interface ObjectA {
  // A sample IPC send to the toy "renderer".
  DoA();
};

// Bound in the renderer process.
interface ObjectB {
  // A sample IPC send to the toy "renderer".
  DoB();
};

// This is a simple generic interface that serves no purpose but to transport a
// message handle from the browser to the renderer. It's just a handle, so it
// requires more type information to actually bind the handle properly on the
// other end (see `Process.GetAssociatedInterface()`).
interface GenericInterface {};

// A process-wide interface that the renderer uses to broker new connections to
// other associated interfaces (see `ObjectA` and `ObjectB` above). This is a
// toy version of `blink.mojom.AssociatedInterfaceProvider`, the mechanism by
// which we bind associated interfaces that span the real browser <=> renderer
// processes in Chromium.
interface Process {
  // A sample IPC send to the toy "renderer"; used by the `01-multi-process`
  // example.
  SayHello();

  // Because we're transporting a generic handle, we need more information to
  // bind it properly in the toy "renderer" process, which is what the "name"
  // argument provides.
  GetAssociatedInterface(
      string name, pending_associated_receiver<GenericInterface> receiver);
};

自动生成 

out\Debug\gen\codelabs\mojo_examples\mojom\interface.mojom.h

out\Debug\gen\codelabs\mojo_examples\mojom\interface.mojom.cc等文件。 

2、BUILD.gn

codelabs\mojo_examples\mojom\BUILD.gn

import("//mojo/public/tools/bindings/mojom.gni")

mojom("mojom") {
  sources = [ "interface.mojom" ]
  public_deps = [
    "//ipc:mojom",
    "//ipc:mojom_constants",
  ]
  deps = [
    "//ipc:mojom",
    "//ipc:mojom_constants",
  ]

  # Don't generate a variant sources since we depend on generated internal
  # bindings types and we don't generate or build variants of those.
  disable_variants = true
}

3、ObjectA和ObjectB接口实现:

codelabs\mojo_examples\mojo_impls.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CODELABS_MOJO_EXAMPLES_MOJO_IMPLS_H_
#define CODELABS_MOJO_EXAMPLES_MOJO_IMPLS_H_

#include "base/task/single_thread_task_runner.h"
#include "codelabs/mojo_examples/mojom/interface.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"

// The classes here are implementations of the mojo interfaces in this
// directory that some of the examples use. They are global instances whose
// receivers get bound to task runners associated with different task queues.
// `ObjectAImpl` is bound to a task queue that is initially frozen, and
// `ObjectBImpl` is bound to the current thread's default task runner,
// associated with an unfrozen task queue.
class ObjectAImpl : public codelabs::mojom::ObjectA {
 public:
  ObjectAImpl();
  ~ObjectAImpl() override;
  void BindToFrozenTaskRunner(
      mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectA>
          pending_receiver,
      scoped_refptr<base::SingleThreadTaskRunner> freezable_tq_runner);

 private:
  // codelabs::mojom::ObjectA
  void DoA() override;

  mojo::AssociatedReceiver<codelabs::mojom::ObjectA> receiver_{this};
};

// The global instance of this class is bound to an unfrozen task queue, but
// doesn't receive any messages until the frozen task queue that manages
// `ObjectAImpl`'s is finally unfroze, after a delay.
class ObjectBImpl : public codelabs::mojom::ObjectB {
 public:
  ObjectBImpl();
  ~ObjectBImpl() override;
  void Bind(mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectB>
                pending_receiver);

 private:
  // codelabs::mojom::ObjectB
  void DoB() override;

  mojo::AssociatedReceiver<codelabs::mojom::ObjectB> receiver_{this};
};

#endif  // CODELABS_MOJO_EXAMPLES_MOJO_IMPLS_H_

codelabs\mojo_examples\mojo_impls.cc 

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "codelabs/mojo_examples/mojo_impls.h"

#include "base/logging.h"

ObjectAImpl::ObjectAImpl() = default;
ObjectAImpl::~ObjectAImpl() = default;

void ObjectAImpl::BindToFrozenTaskRunner(
    mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectA> pending_receiver,
    scoped_refptr<base::SingleThreadTaskRunner> freezable_tq_runner) {
  receiver_.Bind(std::move(pending_receiver), std::move(freezable_tq_runner));
}

void ObjectAImpl::DoA() {
  LOG(INFO) << "DoA IPC is being processed!";
}

ObjectBImpl::ObjectBImpl() = default;
ObjectBImpl::~ObjectBImpl() = default;

void ObjectBImpl::Bind(mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectB>
                           pending_receiver) {
  receiver_.Bind(std::move(pending_receiver));
}

void ObjectBImpl::DoB() {
  LOG(INFO) << "DoB IPC is being processed!";
}

三、02-mojo-browser.exe

codelabs\mojo_examples\02-associated-interface-freezing\browser.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "codelabs/mojo_examples/mojom/interface.mojom.h"
#include "codelabs/mojo_examples/process_bootstrapper.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"

mojo::ScopedMessagePipeHandle LaunchAndConnect() {
  // Under the hood, this is essentially always an OS pipe (domain socket pair,
  // Windows named pipe, mach port, Fuchsia channel, etc).
  mojo::PlatformChannel channel;

  mojo::OutgoingInvitation invitation;

  // Attach a message pipe to be extracted by the receiver. The other end of the
  // pipe is returned for us to use locally.
  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe("pipe");

  base::LaunchOptions options;
  // This is the relative path to the mock "renderer process" binary. We pass it
  // into `base::LaunchProcess` to run the binary in a new process.
  static const base::CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("./02-mojo-renderer")};
  base::CommandLine command_line(1, argv);
  channel.PrepareToPassRemoteEndpoint(&options, &command_line);
  LOG(INFO) << "Browser: " << command_line.GetCommandLineString();
  base::Process child_process = base::LaunchProcess(command_line, options);
  channel.RemoteProcessLaunchAttempted();

  mojo::OutgoingInvitation::Send(std::move(invitation), child_process.Handle(),
                                 channel.TakeLocalEndpoint());
  return pipe;
}

void CreateProcessRemote(mojo::ScopedMessagePipeHandle pipe) {
  // An unassociated remote to the toy "renderer" process. We us this to bind
  // two associated interface requests.
  mojo::PendingRemote<codelabs::mojom::Process> pending_remote(std::move(pipe),
                                                               /*version=*/0u);
  mojo::Remote<codelabs::mojom::Process> remote(std::move(pending_remote));
  remote->SayHello();

  // Make an associated interface request for ObjectA and send an IPC.
  mojo::PendingAssociatedRemote<codelabs::mojom::GenericInterface>
      pending_generic;
  remote->GetAssociatedInterface(
      "ObjectA", pending_generic.InitWithNewEndpointAndPassReceiver());
  mojo::PendingAssociatedRemote<codelabs::mojom::ObjectA> pending_a(
      pending_generic.PassHandle(), /*version=*/0u);
  mojo::AssociatedRemote<codelabs::mojom::ObjectA> remote_a(
      std::move(pending_a));
  LOG(INFO) << "Calling ObjectA::DoA() from the browser";
  remote_a->DoA();

  // Do the same for ObjectB.
  mojo::PendingAssociatedRemote<codelabs::mojom::GenericInterface>
      pending_generic_2;
  remote->GetAssociatedInterface(
      "ObjectB", pending_generic_2.InitWithNewEndpointAndPassReceiver());
  mojo::PendingAssociatedRemote<codelabs::mojom::ObjectB> pending_b(
      pending_generic_2.PassHandle(), /*version=*/0u);
  mojo::AssociatedRemote<codelabs::mojom::ObjectB> remote_b(
      std::move(pending_b));
  LOG(INFO) << "Calling ObjectB::DoB() from the browser";
  remote_b->DoB();
}

int main(int argc, char** argv) {
  LOG(INFO) << "Browser process starting up";
  base::CommandLine::Init(argc, argv);

  ProcessBootstrapper bootstrapper;
  bootstrapper.InitMainThread(base::MessagePumpType::IO);
  bootstrapper.InitMojo(/*as_browser_process=*/true);

  mojo::ScopedMessagePipeHandle pipe = LaunchAndConnect();
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(&CreateProcessRemote, std::move(pipe)));

  base::RunLoop run_loop;
  // Delay shutdown of the browser process for visual effects, as well as to
  // ensure the browser process doesn't die while the IPC message is still being
  // sent to the target process asynchronously, which would prevent its
  // delivery. This delay is an arbitrary 5 seconds, which just needs to be
  // longer than the renderer's 3 seconds, which is used to show visually via
  // logging, how the ordering of IPCs can be effected by a frozen task queue
  // that gets unfrozen 3 seconds later.
  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          [](base::OnceClosure quit_closure) {
            LOG(INFO) << "'Browser process' shutting down";
            std::move(quit_closure).Run();
          },
          run_loop.QuitClosure()),
      base::Seconds(5));
  run_loop.Run();
  return 0;
}

四、02-mojo-renderer.exe

codelabs\mojo_examples\02-associated-interface-freezing\renderer.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/task_queue.h"
#include "codelabs/mojo_examples/mojo_impls.h"
#include "codelabs/mojo_examples/mojom/interface.mojom.h"
#include "codelabs/mojo_examples/process_bootstrapper.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"

static ObjectAImpl g_object_a;
static ObjectBImpl g_object_b;

class ProcessImpl : public codelabs::mojom::Process {
 public:
  ProcessImpl(mojo::PendingReceiver<codelabs::mojom::Process> pending_receiver,
              scoped_refptr<base::SingleThreadTaskRunner> freezable_tq_runner) {
    receiver_.Bind(std::move(pending_receiver));
    freezable_tq_runner_ = std::move(freezable_tq_runner);
  }

 private:
  // codelabs::mojo::Process
  void SayHello() override {
    LOG(INFO) << "Hello! (invoked in the renderer, from the browser)";
  }
  void GetAssociatedInterface(
      const std::string& name,
      mojo::PendingAssociatedReceiver<codelabs::mojom::GenericInterface>
          receiver) override {
    LOG(INFO) << "Renderer: GetAssociatedInterface() for " << name;
    if (name == "ObjectA") {
      mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectA> pending_a(
          receiver.PassHandle());
      g_object_a.BindToFrozenTaskRunner(std::move(pending_a),
                                        std::move(freezable_tq_runner_));
    } else if (name == "ObjectB") {
      mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectB> pending_b(
          receiver.PassHandle());
      g_object_b.Bind(std::move(pending_b));
    }
  }

  mojo::Receiver<codelabs::mojom::Process> receiver_{this};
  // This is a freezable task runner that only `g_object_a` gets bound to.
  scoped_refptr<base::SingleThreadTaskRunner> freezable_tq_runner_;
};

static std::unique_ptr<ProcessImpl> g_process_impl;

class CustomTaskQueue : public base::RefCounted<CustomTaskQueue> {
 public:
  CustomTaskQueue(base::sequence_manager::SequenceManager& sequence_manager,
                  const base::sequence_manager::TaskQueue::Spec& spec)
      : task_queue_(sequence_manager.CreateTaskQueue(spec)),
        voter_(task_queue_->CreateQueueEnabledVoter()) {}
  void FreezeTaskQueue() { voter_->SetVoteToEnable(false); }

  void UnfreezeTaskQueue() {
    LOG(INFO) << "Unfreezing the task queue that `ObjectAImpl` is bound to.";
    voter_->SetVoteToEnable(true);
  }

  const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() const {
    return task_queue_->task_runner();
  }

 private:
  ~CustomTaskQueue() = default;
  friend class base::RefCounted<CustomTaskQueue>;

  base::sequence_manager::TaskQueue::Handle task_queue_;
  // Used to enable/disable the underlying `TaskQueueImpl`.
  std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> voter_;
};

int main(int argc, char** argv) {
  base::CommandLine::Init(argc, argv);
  LOG(INFO) << "Renderer: "
            << base::CommandLine::ForCurrentProcess()->GetCommandLineString();

  // Set up the scheduling infrastructure for this process. It consists of:
  //   1.) A SequenceManager that is bound to the current thread (main thread)
  //   2.) A default task queue
  //   3.) A `CustomTaskQueue` that is easily freezable and unfreezable. This
  //   part is specific to this example.
  ProcessBootstrapper bootstrapper;
  bootstrapper.InitMainThread(base::MessagePumpType::IO);
  bootstrapper.InitMojo(/*as_browser_process=*/false);

  scoped_refptr<CustomTaskQueue> freezable_tq =
      base::MakeRefCounted<CustomTaskQueue>(
          *bootstrapper.sequence_manager.get(),
          base::sequence_manager::TaskQueue::Spec(
              base::sequence_manager::QueueName::TEST_TQ));
  freezable_tq->FreezeTaskQueue();

  // Accept an invitation.
  mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(
      mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
          *base::CommandLine::ForCurrentProcess()));
  mojo::ScopedMessagePipeHandle pipe = invitation.ExtractMessagePipe("pipe");

  base::RunLoop run_loop;

  // Post a task that will run in 3 seconds, that will unfreeze the custom task
  // queue to which the `codelabs::mojom::ObjectA` object is bound to.
  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          [](scoped_refptr<CustomTaskQueue> freezable_tq) {
            freezable_tq->UnfreezeTaskQueue();
          },
          freezable_tq),
      base::Seconds(3));

  // Create a process-wide receiver that will broker connects to the backing
  // `codelabs::mojom::ObjectA` and `codelabs::mojom::ObjectB` implementations.
  mojo::PendingReceiver<codelabs::mojom::Process> pending_receiver(
      std::move(pipe));
  g_process_impl = std::make_unique<ProcessImpl>(std::move(pending_receiver),
                                                 freezable_tq->task_runner());
  run_loop.Run();

  return 0;
}

五、ProcessBootstrapper辅助类

codelabs\mojo_examples\process_bootstrapper.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_H_
#define CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_H_

#include "base/message_loop/message_pump.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"

class ProcessBootstrapper {
 public:
  ProcessBootstrapper();
  ~ProcessBootstrapper();

  // This sets up the main thread with a message pump of `type`, and optionally
  // a dedicated IO thread if `type` is *not* `base::MessagePumpType::IO`.
  void InitMainThread(base::MessagePumpType type) {
    // Creates a sequence manager bound to the main thread with a message pump
    // of some specified type. The message pump determines exactly what the
    // event loop on its thread is capable of (i.e., what *kind* of messages it
    // can "pump"). For example, a `DEFAULT` message pump is capable of
    // processing simple events, like async timers and posted tasks. The `IO`
    // message pump type — which is used in every example in this codelab — is
    // capable of asynchronously processing IO over IPC primitives like file
    // descriptors, used by Mojo. A thread with *that* kind of message pump is
    // required for any process using Mojo for IPC.
    std::unique_ptr<base::MessagePump> pump = base::MessagePump::Create(type);
    sequence_manager =
        base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(
            std::move(pump),
            base::sequence_manager::SequenceManager::Settings::Builder()
                .SetMessagePumpType(type)
                .Build());
    default_tq = std::make_unique<base::sequence_manager::TaskQueue::Handle>(
        sequence_manager->CreateTaskQueue(
            base::sequence_manager::TaskQueue::Spec(
                base::sequence_manager::QueueName::DEFAULT_TQ)));
    sequence_manager->SetDefaultTaskRunner((*default_tq)->task_runner());

    if (type == base::MessagePumpType::DEFAULT) {
      InitDedicatedIOThread();
    }
  }

  // Must be called after `InitMainThread()`.
  void InitMojo(bool as_browser_process) {
    CHECK(default_tq) << "Must call `InitMainThread()` before `InitMojo()`";
    // Basic Mojo initialization for a new process.
    mojo::core::Configuration config;
    // For mojo, one process must be the broker process which is responsible for
    // trusted cross-process introductions etc. Traditionally this is the
    // "browser" process.
    config.is_broker_process = as_browser_process;
    mojo::core::Init(config);

    // The effects of `ScopedIPCSupport` are mostly irrelevant for our simple
    // examples, but this class is used to determine how the IPC system shuts
    // down. The two shutdown options are "CLEAN" and "FAST", and each of these
    // may determine how other processes behave if *this* process has a message
    // pipe that is in the middle of proxying messages to another process where
    // the other end of the message pipe lives.
    //
    // In real Chrome, both the browser and renderer processes can safely use
    // `FAST` mode, because the side effects of quickly terminating the IPC
    // system in the middle of cross-process IPC message proxying is not
    // important. See this class's documentation for more information on
    // shutdown.
    //
    // We initialize `ipc_support` with a task runner for whatever thread should
    // be the IO thread. This means preferring `io_task_runner` when it is
    // non-null, and the default task runner otherwise.
    mojo::core::ScopedIPCSupport ipc_support(
        io_task_runner ? io_task_runner : (*default_tq)->task_runner(),
        mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);
  }

  std::unique_ptr<base::sequence_manager::TaskQueue::Handle> default_tq;
  std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager;
  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner;

 private:
  // Note that you cannot call this if you've ever called
  // `InitMainThread(base::MessagePumpType::IO)` since that means the main
  // thread *itself* the IO thread.
  void InitDedicatedIOThread() {
    io_thread_ = std::make_unique<base::Thread>("ipc!");
    io_thread_->StartWithOptions(
        base::Thread::Options(base::MessagePumpType::IO, 0));
    io_task_runner = io_thread_->task_runner();
  }

  std::unique_ptr<base::Thread> io_thread_;
};

ProcessBootstrapper::ProcessBootstrapper() = default;
ProcessBootstrapper::~ProcessBootstrapper() = default;

#endif  // CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_H_

六、codelabs\mojo_examples\BUILD.gn

# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

group("codelab_mojo_examples") {
  testonly = true

  # These examples rely on base::LaunchOptions which do not exist in the iOS
  # simulator.
  if (!is_ios) {
    deps = [
      ":01-mojo-browser",
      ":01-mojo-renderer",
      ":02-mojo-browser",
      ":02-mojo-renderer",
      ":03-mojo-browser",
      ":03-mojo-renderer",
    ]
  }
}

if (!is_ios) {
  executable("01-mojo-browser") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "01-multi-process/browser.cc",
      "process_bootstrapper.h",
    ]
  }

  executable("01-mojo-renderer") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "01-multi-process/renderer.cc",
      "process_bootstrapper.h",
    ]
  }

  executable("02-mojo-browser") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "02-associated-interface-freezing/browser.cc",
      "process_bootstrapper.h",
    ]
  }

  executable("02-mojo-renderer") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "02-associated-interface-freezing/renderer.cc",
      "mojo_impls.cc",
      "mojo_impls.h",
      "process_bootstrapper.h",
    ]
  }

  executable("03-mojo-browser") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "03-channel-associated-interface-freezing/browser.cc",
      "process_bootstrapper.h",
    ]
  }

  executable("03-mojo-renderer") {
    deps = [
      "//base",
      "//codelabs/mojo_examples/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
    sources = [
      "03-channel-associated-interface-freezing/renderer.cc",
      "mojo_impls.cc",
      "mojo_impls.h",
      "process_bootstrapper.h",
    ]
  }
}

七、编译和调试:

  1、gn gen out/debug

自动生成如下文件:  

2、 ninja -C out/debug 02-mojo-browser

生成02-mojo-browser.exe

3、ninja -C out/debug 02-mojo-renderer

生成02-mojo-renderer.exe

4、最终生成文件:

八、总结:

1、02-mojo-browser.exe 与02-mojo-renderer.exe通过mojo::OutgoingInvitation模式建立链接。

2、02-mojo-browser.exe通过GetAssociatedInterface接口获取02-mojo-renderer.exe进程对应的

ObjectA和ObjectB接口,并且调用其方法DoA(),DoB()。

更多细节读者自行参考源码。

Chromium Mojo(IPC)进程通信演示 c++(3)-CSDN博客


http://www.kler.cn/a/403439.html

相关文章:

  • pinia是什么?pinia简介快速入门,创建pinia到vue3项目中
  • AUTOSAR_EXP_ARAComAPI的7章笔记(6)
  • 使用 FFmpeg 提取音频的详细指南
  • 设计模式之 状态模式
  • 2024信创数据库TOP30之蚂蚁集团OceanBase
  • 数据库笔记1
  • 实验室管理技术革新:Spring Boot系统
  • 什么是事务,事务有什么特性?
  • 大语言模型的多头切片技术在分布式机器上的运行,每个机器是否需加载完整模型参数?无需加载完整模型参数
  • TAIS 软件管理系统深入分析
  • 工作学习--Arrays.asList的问题
  • Linux相关概念和易错知识点(21)(软硬链接、动静态库)
  • 丹摩智算(damodel)部署stable diffusion心得
  • js中的=、==与===的区别
  • linux先创建文件夹后指定创建文件夹用户
  • DataGear 企业版 1.3.0 发布,数据可视化分析平台
  • java-搜索算法
  • java ssm 新青年在线学习网 学习网站 学习系统 学习平台 源码jsp
  • VMware Workstation 17.6.1
  • 开发者视角下的鸿蒙
  • 沸蛇鼠标,多功能智慧AI,重新定义生产力
  • 华为云鸿蒙应用入门级开发者认证考试题库(理论题和实验题)
  • Android12 Wifi的连接过程梳理
  • LeetCode 209 长度最小的子数组(滑动窗口)
  • 前端学习八股资料CSS(五)
  • nodejs21: 快速构建自定义设计样式Tailwind CSS