跳至主要内容

创建新的 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 是具有相应 v8 包装器对象的 C++ 对象的基类。

这是一个您可能需要添加的基本代码示例,以便将 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 文件中,将您的节点绑定名称添加到 Electron 的内置模块中。

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

注意:有关 Node 如何与 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') },
];