跳转到主要内容

创建新的 Electron 浏览器模块

欢迎阅读 Electron API 指南!如果您不熟悉在 browser 目录中创建新的 Electron API 模块,本指南将为您提供一些您需要实现的必要步骤的清单。

这并不是一个关于创建 Electron 浏览器 API 的全面详尽的指南,而是一个记录了一些不太直观的步骤的概述。

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

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

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

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 有特定的平台实现时才应添加。

创建 API 文档

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

设置 ObjectTemplateBuilderWrappable

Electron 使用 object_template_builder 构建其模块。

Wrappable 是 C++ 对象的一个基类,它具有相应的 v8 包装器对象。

以下是您可能需要添加的代码的一个基本示例,以便将 object_template_builderwrappable 整合到您的 API 中。有关更多参考,您可以在 此处 找到更多实现。

在您的 api_name.h 文件中

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 文件中

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

typings/internal-ambient.d.ts 文件中,我们需要像这样向 Process 接口添加一个新属性

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

在您的 api_name.cc 文件最底部

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

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

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

有关 Node.js 如何与 Electron 链接的更多技术细节,请参阅 我们的博客

将您的 API 暴露给 TypeScript

将您的 API 导出为模块

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

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

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

将您的模块暴露给 TypeScript

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

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