Skip to main content

Swift + JavaScriptCore

JavaScript 核心 (JSC) 是为 Safari Web 浏览器提供支持的 JavaScript 引擎。

¥JavaScriptCore (JSC) is the JavaScript engine powering the Safari web browser.

SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。

¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.

该演示使用 JSC 和 SheetJS 来读取和写入电子表格。我们将探讨如何在 JSC 上下文中加载 SheetJS,并处理来自 C++ 和 Swift 程序的电子表格和结构化数据。

¥This demo uses JSC and SheetJS to read and write spreadsheets. We'll explore how to load SheetJS in a JSC context and process spreadsheets and structured data from C++ and Swift programs.

本 demo 在以下环境下进行了测试:

¥This demo was tested in the following environments:

Swift 内置

¥Swift Built-in

MacOS 上的 Swift 支持 JavaScriptCore,无需额外依赖。

¥Swift on MacOS supports JavaScriptCore without additional dependencies.

架构迅速日期
darwin-x646.12025-04-21
darwin-arm6.12025-04-21

C / C++ Compiled from Source

JavaScriptCore 可以从源代码构建并链接到 C/C++ 程序中。

¥JavaScriptCore can be built from source and linked in C / C++ programs.

架构版本日期
darwin-x647620.2.4.111.72025-04-21
darwin-arm7620.2.4.111.72025-04-21
linux-x647620.2.4.111.72025-04-21
linux-arm7620.2.4.111.72025-04-21

从源代码编译的 Swift

¥Swift Compiled from Source

Swift 编译器可以链接到从 JavaScriptCore 源构建的库。

¥Swift compiler can link against libraries built from the JavaScriptCore source.

架构版本日期
linux-x647620.2.4.111.72025-04-21
linux-arm7620.2.4.111.72025-04-21

集成详情

¥Integration Details

SheetJS 独立脚本 可以在 JSC 上下文中进行解析和评估。

¥The SheetJS Standalone scripts can be parsed and evaluated in a JSC context.

可以使用 String.Encoding.isoLatin1 来回传递二进制字符串。

¥Binary strings can be passed back and forth using String.Encoding.isoLatin1.

SheetJS read 方法 [^1],具有 "binary" 类型,可以解析二进制字符串。

¥The SheetJS read method[^1], with the "binary" type, can parse binary strings.

write 方法 [^2],具有 "binary" 类型,可以创建二进制字符串。

¥The write method[^2], with the "binary" type, can create binary strings.

初始化 JSC

¥Initialize JSC

可以使用 JSContext 函数创建 JSC 上下文:

¥A JSC context can be created with the JSContext function:

var context: JSContext!
do {
context = JSContext();
context.exceptionHandler = { _, X in if let e = X { print(e.toString()!); }; };
} catch { print(error.localizedDescription); }

JSC 不提供 global 变量。它可以在一行中创建:

¥JSC does not provide a global variable. It can be created in one line:

do {
context.evaluateScript("var global = (function(){ return this; }).call(null);");
} catch { print(error.localizedDescription); }

加载 SheetJS 脚本

¥Load SheetJS Scripts

可以通过从文件系统读取脚本并在 JSC 上下文中进行评估来加载主库:

¥The main library can be loaded by reading the scripts from the file system and evaluating in the JSC context:

let src = try String(contentsOfFile: "xlsx.full.min.js");
context.evaluateScript(src);

要确认库已加载,可以检查 XLSX.version

¥To confirm the library is loaded, XLSX.version can be inspected:

let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX");
if let ver = XLSX.objectForKeyedSubscript("version") { print(ver.toString()); }

读取文件

¥Reading Files

String(contentsOf:encoding:) 从路径读取并返回编码字符串:

¥String(contentsOf:encoding:) reads from a path and returns an encoded string:

/* read sheetjs.xls as Base64 string */
let file_path = shared_dir.appendingPathComponent("sheetjs.xls");
let data: String! = try String(contentsOf: file_path, encoding: String.Encoding.isoLatin1);

该字符串可以加载到 JS 引擎中并进行处理:

¥This string can be loaded into the JS engine and processed:

/* load data in JSC */
context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol));

/* `payload` (the "forKeyedSubscript" parameter) is a binary string */
context.evaluateScript("var wb = XLSX.read(payload, {type:'binary'});");
Direct Read (click to show)

Uint8Array data can be passed directly, skipping string encoding and decoding:

let url = URL(fileURLWithPath: file)
var data: Data! = try Data(contentsOf: url);
let count = data.count;
/* Note: the operations must be performed in the closure! */
let wb: JSValue! = data.withUnsafeMutableBytes { (dataPtr: UnsafeMutableRawBufferPointer) in
let ab: JSValue! = JSValue(jsValueRef: JSObjectMakeTypedArrayWithBytesNoCopy(context.jsGlobalContextRef, kJSTypedArrayTypeUint8Array, dataPtr.baseAddress, count, nil, nil, nil), in: context)
/* prepare options argument */
context.evaluateScript(String(format: "var readopts = {type:'array', dense:true}"));
let readopts: JSValue = context.objectForKeyedSubscript("readopts");
/* call XLSX.read */
let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX");
let readfunc: JSValue = XLSX.objectForKeyedSubscript("read");
return readfunc.call(withArguments: [ab, readopts]);
}

For broad compatibility with Swift versions, the demo uses the String method.

写入文件

¥Writing Files

在 JavaScriptCore 中写入二进制字符串时,结果应存储在变量中并在 Swift 中转换为字符串:

¥When writing to binary string in JavaScriptCore, the result should be stored in a variable and converted to string in Swift:

/* write to binary string */
context.evaluateScript("var out = XLSX.write(wb, {type:'binary', bookType:'xlsx'})");

/* `out` from the script is a binary string that can be stringified in Swift */
let outvalue: JSValue! = context.objectForKeyedSubscript("out");
var out: String! = outvalue.toString();

String#write(to:atomically:encoding) 将字符串写入指定路径:

¥String#write(to:atomically:encoding) writes the string to the specified path:

/* write to sheetjsw.xlsx */
let out_path = shared_dir.appendingPathComponent("sheetjsw.xlsx");
try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLatin1);

完整示例

¥Complete Example

迅速

¥Swift

该演示包含一个示例 SheetJSCore Wrapper 类来简化操作。

¥The demo includes a sample SheetJSCore Wrapper class to simplify operations.

该演示仅在 MacOS 上运行

此示例需要 MacOS + Swift,不适用于 Windows 或 Linux!

¥This example requires MacOS + Swift and will not work on Windows or Linux!

"Swift C" 部分介绍了在其他平台中的集成。

¥The "Swift C" section covers integration in other platforms.

  1. 通过在终端中运行以下命令确保已安装 Swift:

    ¥Ensure Swift is installed by running the following command in the terminal:

swiftc --version

如果未找到该命令,请安装 Xcode。

¥If the command is not found, install Xcode.

  1. 为项目创建一个文件夹:

    ¥Create a folder for the project:

mkdir sheetjswift
cd sheetjswift
  1. 下载 SheetJS Standalone 脚本和测试文件。将这两个文件保存在项目目录中:

    ¥Download the SheetJS Standalone script and the test file. Save both files in the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载演示的 Swift 脚本

    ¥Download the Swift scripts for the demo

curl -LO https://xlsx.nodejs.cn/swift/SheetJSCore.swift
curl -LO https://xlsx.nodejs.cn/swift/main.swift
  1. 构建 SheetJSwift 程序:

    ¥Build the SheetJSwift program:

swiftc SheetJSCore.swift main.swift -o SheetJSwift
  1. 测试程序:

    ¥Test the program:

./SheetJSwift pres.numbers

如果成功,CSV 将打印到控制台。该脚本还尝试写入 SheetJSwift.xlsx。该文件可以通过在 Excel/Numbers 中打开来验证。

¥If successful, a CSV will be printed to console. The script also tries to write to SheetJSwift.xlsx. That file can be verified by opening in Excel / Numbers.

C++

此演示的旧版本建议下载 WebKit 发行存档。

¥Older versions of this demo recommended downloading the WebKit release archives.

Microsoft 已禁用所有 WebKit 存档下载!

¥Microsoft disabled all WebKit archive downloads!

上次测试演示时,https://codeload.github.com/WebKit/WebKit/zip/refs/tags/WebKit-7620.2.4.111.7 返回 HTTP 422 Archive creation is blocked

¥https://codeload.github.com/WebKit/WebKit/zip/refs/tags/WebKit-7620.2.4.111.7 , when the demo was last tested, returned HTTP 422 Archive creation is blocked.

更新后的说明现在克隆了代码库。获取和存储代码需要额外的 20GB 存储空间和 11GB 带宽。

¥The updated instructions now clone the repository. An additional 20GB of storage space and 11GB of bandwidth is required to fetch and store the code.

  1. 安装依赖

    ¥Install dependencies

Installation Notes (click to show)

The build requires CMake and Ruby.

On macOS, dependencies should be installed with brew:

brew install cmake ruby

On the Steam Deck, dependencies should be installed with pacman:

sudo pacman -Syu base-devel cmake ruby icu glibc linux-api-headers

On Debian and Ubuntu, dependencies should be installed with apt:

sudo apt-get install build-essential cmake ruby
  1. 创建项目文件夹:

    ¥Create a project folder:

mkdir sheetjs-jsc
cd sheetjs-jsc
  1. 克隆 WebKit 代码库并切换到 WebKit-7620.2.4.111.7 标签:

    ¥Clone the WebKit repository and switch to the WebKit-7620.2.4.111.7 tag:

git clone https://github.com/WebKit/WebKit.git WebKit
cd WebKit
git checkout WebKit-7620.2.4.111.7
cd ..
  1. 构建 JavaScriptCore:

    ¥Build JavaScriptCore:

cd WebKit
env CFLAGS="-Wno-error=all -Wno-deprecated-declarations" CXXFLAGS="-Wno-error=all -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\"" --make-args="-Wno-error=all -Wno-deprecated-declarations"
cd ..

在 ARM64 macOS 上的某些测试运行中,JIT 引发运行时错误,而 WebAssembly 引发编译时错误。应禁用 WebAssembly 和 JIT:

¥In some test runs on ARM64 macOS, JIT elicited runtime errors and WebAssembly elicited compile-time errors. WebAssembly and JIT should be disabled:

cd WebKit
env CFLAGS="-Wno-error=all -Wno-deprecated-declarations" CXXFLAGS="-Wno-error=all -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\"" --make-args="-Wno-error=all -Wno-deprecated-declarations" --no-jit --no-webassembly
cd ..

在一些测试运行中,构建失败并显示错误消息:

¥In some test runs, the build failed with the error message

Source/WTF/wtf/text/ASCIILiteral.h:65:34: error: use of undeclared identifier 'NSString'
WTF_EXPORT_PRIVATE RetainPtr<NSString> createNSString() const;
^
1 error generated.

必须修补引用的头文件以声明 NSString

¥The referenced header file must be patched to declare NSString:

Source/WTF/wtf/text/ASCIILiteral.h (add highlighted lines)
#include <wtf/text/SuperFastHash.h>

#ifdef __OBJC__
@class NSString;
#endif

namespace WTF {

在一些测试运行中,构建失败并显示错误消息:

¥In some test runs, the build failed with the error message

Source/JavaScriptCore/runtime/JSCBytecodeCacheVersion.cpp:37:10: fatal error: 'wtf/spi/darwin/dyldSPI.h' file not found
#include <wtf/spi/darwin/dyldSPI.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

#include 应更改为相对指令:

¥The #include should be changed to a relative directive:

Source/JavaScriptCore/runtime/JSCBytecodeCacheVersion.cpp (edit highlighted lines)
#include <wtf/NeverDestroyed.h>
#include "../../WTF/wtf/spi/darwin/dyldSPI.h"
#endif
  1. 创建指向源树中 Release 文件夹的符号链接:

    ¥Create a symbolic link to the Release folder in the source tree:

ln -s WebKit/WebKitBuild/JSCOnly/Release .
  1. 下载 sheetjs-jsc.c

    ¥Download sheetjs-jsc.c:

curl -LO https://xlsx.nodejs.cn/jsc/sheetjs-jsc.c
  1. 编译程序 x:

    ¥Compile the program:

g++ -o sheetjs-jsc sheetjs-jsc.c -IRelease/JavaScriptCore/Headers -LRelease/lib -lbmalloc -licucore -lWTF -lJavaScriptCore -IRelease/JavaScriptCore/Headers -framework Foundation

在某些测试运行中,出现有关 macOS 版本的 ld 警告:

¥In some test runs, there were ld warnings about macOS versions:

ld: warning: object file (Release/lib/libWTF.a[2](ASCIICType.cpp.o)) was built for newer 'macOS' version (14.5) than being linked (14.0)

这些警告可以忽略。

¥These warnings can be ignored.

  1. 下载 SheetJS Standalone 脚本和测试文件。将这两个文件保存在项目目录中:

    ¥Download the SheetJS Standalone script and the test file. Save both files in the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 运行程序:

    ¥Run the program:

./sheetjs-jsc pres.numbers

如果成功,CSV 将打印到控制台。该脚本还尝试写入 sheetjsw.xlsb,该文件可以在电子表格编辑器中打开。

¥If successful, a CSV will be printed to console. The script also tries to write to sheetjsw.xlsb, which can be opened in a spreadsheet editor.

Swift C

对于 macOS 和 iOS 部署,强烈建议使用官方 JavaScriptCore 绑定。此演示适用于 Linux Swift 应用。

¥For macOS and iOS deployments, it is strongly encouraged to use the official JavaScriptCore bindings. This demo is suited for Linux Swift applications.

  1. 安装 Swift 工具链.[^8]

    ¥Install the Swift toolchain.[^8]

Installation Notes (click to show)

The linux-x64 test was run on Ubuntu 22.04 using Swift 6.1

The linux-arm test was run on Debian 12 "bookworm" using Swift 6.1

  1. 遵循整个 "C" 演示。共享库将在 Swift 中使用。

    ¥Follow the entire "C" demo. The shared library will be used in Swift.

  2. 输入上一步中的 sheetjs-jsc 文件夹。

    ¥Enter the sheetjs-jsc folder from the previous step.

  3. 创建文件夹 sheetjswift。它应该在 sheetjs-jsc 文件夹中:

    ¥Create a folder sheetjswift. It should be in the sheetjs-jsc folder:

mkdir sheetjswift
cd sheetjswift
  1. 下载 SheetJS Standalone 脚本和测试文件。将这两个文件保存在项目目录中:

    ¥Download the SheetJS Standalone script and the test file. Save both files in the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 将所有生成的标题复制到当前目录:

    ¥Copy all generated headers to the current directory:

find ../WebKit/WebKitBuild/JSCOnly/Release/JavaScriptCore/Headers/  -name \*.h | xargs -I '%' cp '%' .
  1. 编辑每个头文件并将 <JavaScriptCore/ 的所有实例替换为 <。例如,JavaScript.h 包括 <JavaScriptCore/JSBase.h>

    ¥Edit each header file and replace all instances of <JavaScriptCore/ with <. For example, JavaScript.h includes <JavaScriptCore/JSBase.h>:

JavaScript.h (original include)
#include <JavaScriptCore/JSBase.h>

必须将其更改为 <JSBase.h>

¥This must be changed to <JSBase.h>:

JavaScript.h (modified include)
#include <JSBase.h>
  1. 打印当前工作目录。它将是 sheetjswift 的路径:

    ¥Print the current working directory. It will be the path to sheetjswift:

pwd
  1. 创建一个名为 JavaScriptCore-Bridging-Header.h 的新标题:

    ¥Create a new header named JavaScriptCore-Bridging-Header.h :

JavaScriptCore-Bridging-Header.h
#import "/tmp/sheetjs-jsc/sheetjswift/JavaScript.h"

替换步骤 7 中工作目录的导入路径。例如,如果路径是 /home/sheetjs/sheetjs-jsc/sheetjswift/,则导入应该是

¥Replace the import path to the working directory from step 7. For example, if the path was /home/sheetjs/sheetjs-jsc/sheetjswift/, the import should be

JavaScriptCore-Bridging-Header.h
#import "/home/sheetjs/sheetjs-jsc/JavaScript.h"
  1. 创建默认模块映射 module.modulemap

    ¥Create the default module map module.modulemap:

module.modulemap
module JavaScriptCore {
header "./JavaScript.h"
link "JavaScriptCore"
}
  1. 下载 SheetJSCRaw.swift

    ¥Download SheetJSCRaw.swift:

curl -LO https://xlsx.nodejs.cn/swift/SheetJSCRaw.swift
  1. 构建 SheetJSwift

    ¥Build SheetJSwift:

swiftc -Xcc -I$(pwd) -Xlinker -L../WebKit/WebKitBuild/JSCOnly/Release/lib/ -Xlinker -lJavaScriptCore -Xlinker -lWTF -Xlinker -lbmalloc -Xlinker -lstdc++ -Xlinker -latomic -Xlinker -licuuc -Xlinker -licui18n -import-objc-header JavaScriptCore-Bridging-Header.h SheetJSCRaw.swift -o SheetJSwift
  1. 运行命令:

    ¥Run the command:

./SheetJSwift pres.numbers

如果成功,CSV 将打印到控制台。程序还尝试写入 SheetJSwift.xlsx,可在电子表格编辑器中打开。

¥If successful, a CSV will be printed to console. The program also tries to write to SheetJSwift.xlsx, which can be opened in a spreadsheet editor.

绑定

¥Bindings

在其他编程语言构建的程序中,可以直接加载平台原生 (macOS) 或已编译的库。

¥It is straightforward to load the platform-native (macOS) or compiled libraries in programs built in other programming languages.

JavaScriptCore C 接口不使用 "blingos"(类似函数的宏),因此可以在外部绑定中引用每个方法。

¥The JavaScriptCore C interface does not use "blingos" (function-like macros), so it is possible to reference each method in an external binding.

Rust

编写绑定相当机械化。此过程分为 4 个部分:

¥Writing bindings is fairly mechanical. There are 4 parts to the process:

  1. 链接到外部库。

    ¥Link to the external library.

  2. 生成原始 C 数据类型的 Rust 表示。

    ¥Generate Rust representations of the original C data types.

  3. 翻译函数声明。

    ¥Translate the function declaration.

  4. 编写一个封装器来在 Rust 概念和 C 概念之间进行转换。

    ¥Write a wrapper to convert between Rust concepts and C concepts.

例如,以下 C 代码在引擎中根据 UTF8 字符串创建一个字符串:

¥For example, the following C code creates a string within the engine from a UTF8 string:

Sample use of JSStringCreateWithUTF8CString
const char *code = "'Sheet' + 'JS'";
JSStringRef script = JSStringCreateWithUTF8CString(code);

一个符合人机工程学的封装函数将接受 Rust 字符串字面量并处理不安全的数据操作:

¥An ergonomic wrapper function would take a Rust string literal and handle unsafe data operations:

Theoretical equivalent in Rust
let code: &str = "'Sheet' + 'JS'";
let script: JSStringRef = JSC::JSStringCreateWithUTF8CString(code);

Rust Linkage

自定义指令通常会添加到 build.rscargo::rustc-link-lib 指令指示 Rust 编译器链接到外部库。

¥Custom directives are typically added to build.rs. The cargo::rustc-link-lib directive instructs the Rust compiler to link against an external library.

以下代码片段将指示工具链链接到 macOS 上的系统 JavaScriptCore.framework 框架:

¥The following snippet will instruct the toolchain to link against the system JavaScriptCore.framework framework on macOS:

build.rs (link to JavaScriptCore.framework on macOS)
#[cfg(target_os = "macos")]
fn main() {
println!("cargo::rustc-link-lib=framework=JavaScriptCore");
}

Rust 类型

¥Rust Types

JSStringRef 是一个指向不透明数据类型的指针。根据 Rustonomicon,其精神等价物是一个指向不透明结构体 [^9] 的指针:

¥JSStringRef is a pointer to an opaque data type. The spiritual equivalent according to the Rustonomicon is a pointer to an opaque struct[^9]:

JSStringRef opaque type in Rust
#[repr(C)]
pub struct JSString {
_data: [u8; 0],
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
type JSStringRef = *mut JSContext;

函数声明

¥Function Declaration

JSStringCreateWithUTF8CString 函数在 C 语言中声明如下:

¥The JSStringCreateWithUTF8CString function is declared in C as follows:

JSStringRef JSStringCreateWithUTF8CString(const char * string);

必须在 extern "C" 块中定义等效的 Rust 声明:

¥The equivalent Rust declaration must be defined in an extern "C" block:

JSStringCreateWithUTF8CString Rust declaration
unsafe extern "C" {
// JSStringRef JSStringCreateWithUTF8CString(const char * string);
pub unsafe fn JSStringCreateWithUTF8CString(string: *const u8) -> JSStringRef;
}

Rust Interchange

std::ffi 模块包含许多用于在 Rust 代码和 C 库之间传递数据的辅助函数。

¥The std::ffi module includes a number of helpers for passing data between Rust code and C libraries.

Rust 字符串字面量通常表示为 &str 类型:

¥Rust string literals are commonly represented as &str types:

let script: &str = "'Sheet' + 'JS'"; // 'Sheet' + 'JS'

以下不安全的华尔兹语句创建了一个兼容指针:

¥The following unsafe waltz creates a compatible pointer:

A) 将 &str 转换为字节切片

¥A) Convert the &str to a byte slice

B) 从字节创建 std::ffi::CString 实例

¥B) Create a std::ffi::CString instance from the bytes

C) 使用 as_ptr 方法生成指针

¥C) Use the as_ptr method to generate a pointer

Generate a JSString from a Rust string literal
/* start with a string literal */
let script: &str = "'Sheet' + 'JS'";

/* generate CString */
let cstr: std::ffi::CString = std::ffi::CString::new(script.as_bytes()).unwrap();

/* call JSStringCreateWithUTF8CString */
let ref: JSStringRef = JSStringCreateWithUTF8CString(cstr.as_ptr() as *const u8);

该演示程序创建了一个安全的封装器,只需一行代码即可完成不安全的华尔兹:

¥The demo makes a safe wrapper to perform the unsafe waltz in one line:

Ergonomic wrapper for JSStringCreateWithUTF8CString
pub struct JSC;
impl JSC {
pub fn JSStringCreateWithUTF8CString(str: &str) -> JSStringRef { unsafe {
JSStringCreateWithUTF8CString(std::ffi::CString::new(str.as_bytes()).unwrap().as_ptr() as *const u8)
} }
}

Rust 示例

¥Rust Example

测试部署

该演示最后在以下部署中进行了测试:

¥This demo was last tested in the following deployments:

架构日期
darwin-x642025-03-31
darwin-arm2025-03-30
  1. 创建一个新项目:

    ¥Create a new project:

cargo new sheetjs-jsc
cd sheetjs-jsc
cargo run
  1. 将 SheetJS 独立脚本下载到项目中的 src 文件夹:

    ¥Download the SheetJS Standalone script to the src folder in the project:

curl -L -o src/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
  1. 将测试文件下载到项目目录:

    ¥Download the test file to the project directory:

curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载 main.rs 并替换 src/main.rs

    ¥Download main.rs and replace src/main.rs:

curl -L -o src/main.rs https://xlsx.nodejs.cn/jsc/main.rs
  1. 下载 build.rs 到项目文件夹:

    ¥Download build.rs to the project folder:

curl -LO https://xlsx.nodejs.cn/jsc/build.rs
  1. 构建并运行应用:

    ¥Build and run the app:

cargo run pres.numbers

如果程序成功,CSV 内容将打印到控制台并创建文件 sheetjsw.xlsb。可以使用支持 XLSB 电子表格的电子表格编辑器打开该文件。

¥If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with a spreadsheet editor that supports XLSB spreadsheets.

[^1]: 见 read 于 "读取文件"

¥See read in "Reading Files"

[^2]: 见 writeFile 于 "写入文件"

¥See writeFile in "Writing Files"

[^3]: 请参阅 JavaScriptCore 文档中的 JSObjectMakeTypedArrayWithBytesNoCopy

¥See JSObjectMakeTypedArrayWithBytesNoCopy in the JavaScriptCore documentation.

[^4]: 请参阅 JavaScriptCore 文档中的 JSObjectGetTypedArrayLength

¥See JSObjectGetTypedArrayLength in the JavaScriptCore documentation.

[^5]: 请参阅 JavaScriptCore 文档中的 JSObjectGetTypedArrayBytesPtr

¥See JSObjectGetTypedArrayBytesPtr in the JavaScriptCore documentation.

[^6]: 见 read 于 "读取文件"

¥See read in "Reading Files"

[^7]: 见 writeFile 于 "写入文件"

¥See writeFile in "Writing Files"

[^8]: 有关 Swift 网站中的 "安装 Swift"

¥See "Install Swift" in the Swift website.

[^9]: 请参阅 Rustonomicon 中的 "表示不透明结构体"

¥See "Representing opaque structs" in the Rustonomicon