Skip to main content

创建新的 Electron 浏览器模块

¥Creating a New Electron Browser Module

欢迎来到 Electron API 指南!如果你不熟悉在 browser 目录中创建新的 Electron API 模块,本指南可作为你需要实现的一些必要步骤的清单。

¥Welcome to the Electron API guide! If you are unfamiliar with creating a new Electron API module within the browser directory, this guide serves as a checklist for some of the necessary steps that you will need to implement.

这不是创建 Electron 浏览器 API 的全面的最终指南,而是记录了一些更不直观的步骤的大纲。

¥This is not a comprehensive end-all guide to creating an Electron Browser API, rather an outline documenting some of the more unintuitive steps.

将你的文件添加到 Electron 的项目配置中

¥Add your files to Electron's project configuration

Electron 使用 GN 作为元构建系统为其编译器 忍者 生成文件。这意味着为了告诉 Electron 编译你的代码,我们必须将你的 API 代码和头文件名添加到 filenames.gni.h 中。

¥Electron uses GN as a meta build system to generate files for its compiler, Ninja. This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into filenames.gni.

你需要将 API 文件名按字母顺序附加到相应的文件中,如下所示:

¥You will need to append your API file names alphabetically into the appropriate files like so:

filenames.gni
lib_sources = [
"path/to/api/api_name.cc",
"path/to/api/api_name.h",
]

lib_sources_mac = [
"path/to/api/api_name_mac.h",
"path/to/api/api_name_mac.mm",
]

lib_sources_win = [
"path/to/api/api_name_win.cc",
"path/to/api/api_name_win.h",
]

lib_sources_linux = [
"path/to/api/api_name_linux.cc",
"path/to/api/api_name_linux.h",
]

请注意,Windows、macOS 和 Linux 数组添加是可选的,仅当你的 API 具有特定平台实现时才应添加。

¥Note that the Windows, macOS and Linux array additions are optional and should only be added if your API has specific platform implementations.

创建 API 文档

¥Create API documentation

类型定义由 Electron 使用 @electron/docs-parser@electron/typescript-definitions 生成。为了确保 Electron 的 API 文档的一致性,此步骤是必要的。这意味着,为了让你的 API 类型定义出现在 electron.d.ts 文件中,我们必须创建一个 .md 文件。例子可以在 这个文件夹 中找到。

¥Type definitions are generated by Electron using @electron/docs-parser and @electron/typescript-definitions. This step is necessary to ensure consistency across Electron's API documentation. This means that for your API type definition to appear in the electron.d.ts file, we must create a .md file. Examples can be found in this folder.

设置 ObjectTemplateBuilderWrappable

¥Set up ObjectTemplateBuilder and Wrappable

Electron 使用 object_template_builder 构建其模块。

¥Electron constructs its modules using object_template_builder.

wrappable 是具有相应 v8 封装对象的 C++ 对象的基类。

¥wrappable is a base class for C++ objects that have corresponding v8 wrapper objects.

以下是你可能需要添加的基本代码示例,以便将 object_template_builderwrappable 合并到你的 API 中。如需进一步参考,你可以找到更多实现 此处

¥Here is a basic example of code that you may need to add, in order to incorporate object_template_builder and wrappable into your API. For further reference, you can find more implementations here.

在你的 api_name.h 文件中:

¥In your api_name.h file:

api_name.h

#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_

#include "gin/handle.h"
#include "gin/wrappable.h"

namespace electron {

namespace api {

class ApiName : public gin::Wrappable<ApiName> {
public:
static gin::Handle<ApiName> Create(v8::Isolate* isolate);

// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
} // namespace api
} // namespace electron

在你的 api_name.cc 文件中:

¥In your api_name.cc file:

api_name.cc
#include "shell/browser/api/electron_api_safe_storage.h"

#include "shell/browser/browser.h"
#include "shell/common/gin_converters/base_converter.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/platform_util.h"

namespace electron {

namespace api {

gin::WrapperInfo ApiName::kWrapperInfo = {gin::kEmbedderNativeGin};

gin::ObjectTemplateBuilder ApiName::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::ObjectTemplateBuilder(isolate)
.SetMethod("methodName", &ApiName::methodName);
}

const char* ApiName::GetTypeName() {
return "ApiName";
}

// static
gin::Handle<ApiName> ApiName::Create(v8::Isolate* isolate) {
return gin::CreateHandle(isolate, new ApiName());
}

} // namespace api

} // namespace electron

namespace {

void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
gin_helper::Dictionary dict(isolate, exports);
dict.Set("apiName", electron::api::ApiName::Create(isolate));
}

} // namespace

¥Link your Electron API with Node

typings/internal-ambient.d.ts 文件中,我们需要将一个新属性附加到 Process 接口上,如下所示:

¥In the typings/internal-ambient.d.ts file, we need to append a new property onto the Process interface like so:

typings/internal-ambient.d.ts
interface Process {
_linkedBinding(name: 'electron_browser_{api_name}'): Electron.ApiName;
}

api_name.cc 文件的最底部:

¥At the very bottom of your api_name.cc file:

api_name.cc
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{api_name},Initialize)

shell/common/node_bindings.cc 文件中,将节点绑定名称添加到 Electron 的内置模块中。

¥In your shell/common/node_bindings.cc file, add your node binding name to Electron's built-in modules.

shell/common/node_bindings.cc
#define ELECTRON_BROWSER_MODULES(V)      \
V(electron_browser_{api_name})

注意:有关 Node 如何与 Electron 链接的更多技术细节可以在 我们的博客 上找到。

¥Note: More technical details on how Node links with Electron can be found on our blog.

将你的 API 公开给 TypeScript

¥Expose your API to TypeScript

将你的 API 导出为模块

¥Export your API as a module

我们需要在以下路径中创建一个新的 TypeScript 文件:

¥We will need to create a new TypeScript file in the path that follows:

"lib/browser/api/{electron_browser_{api_name}}.ts"

该文件内容的示例可以在 此处.txt 中找到。

¥An example of the contents of this file can be found here.

将你的模块公开给 TypeScript

¥Expose your module to TypeScript

将你的模块添加到 "lib/browser/api/module-list.ts" 处的模块列表中,如下所示:

¥Add your module to the module list found at "lib/browser/api/module-list.ts" like so:

lib/browser/api/module-list.ts
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'apiName', loader: () => require('./api-name') },
];