forked from sheetjs/docs.sheetjs.com
		
	hermes-windows-x64
This commit is contained in:
		
							parent
							
								
									06e7413d36
								
							
						
					
					
						commit
						2c60a9483f
					
				| @ -135,6 +135,30 @@ static char *read_file(const char *filename, size_t *sz) { | ||||
|   size_t sz; char *xlsx_full_min_js = read_file("xlsx.full.min.js", &sz); | ||||
| ``` | ||||
| 
 | ||||
| :::caution pass | ||||
| 
 | ||||
| For Windows applications, the string must be null-terminated: | ||||
| 
 | ||||
| ```cpp | ||||
| /* Hermes-Windows requires the null terminator */ | ||||
| static char *read_file_null(const char *filename, size_t *sz) { | ||||
|   FILE *f = fopen(filename, "rb"); | ||||
|   if(!f) return NULL; | ||||
|   long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); } | ||||
|   char *buf = (char *)malloc(fsize * sizeof(char)); | ||||
|   *sz = fread((void *) buf, 1, fsize, f); | ||||
|   buf[fsize - 1] = 0; | ||||
|   fclose(f); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| // ... | ||||
|   /* read SheetJS library from filesystem */ | ||||
|   size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz); | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| _Hermes Wrapper_ | ||||
| 
 | ||||
| Hermes does not provide a friendly way to prepare JavaScript code stored in a | ||||
| @ -343,13 +367,20 @@ This demo was tested in the following deployments: | ||||
| | `linux-x64`  | `49e1930`  | 2023-09-22 | | ||||
| | `linux-arm`  | `70af78b`  | 2023-08-27 | | ||||
| 
 | ||||
| The main Hermes source tree does not have Windows support. The `hermes-windows` | ||||
| fork, which powers React Native for Windows, does have built-in support[^5] | ||||
| 
 | ||||
| | Architecture | Git Commit | Date       | | ||||
| |:-------------|:-----------|:-----------| | ||||
| | `win10-x64`  | `c7a4a82`  | 2023-09-27 | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 0) Install [dependencies](https://hermesengine.dev/docs/building-and-running/#dependencies) | ||||
| 
 | ||||
| <details><summary><b>Installation Notes</b> (click to show)</summary> | ||||
| 
 | ||||
| The official guidance[^5] has been verified in macOS and HoloOS (Linux). | ||||
| The official guidance[^6] has been verified in macOS and HoloOS (Linux). | ||||
| 
 | ||||
| On macOS: | ||||
| 
 | ||||
| @ -424,6 +455,158 @@ curl -LO https://sheetjs.com/pres.numbers`} | ||||
| If successful, the program will print the library version number and the | ||||
| contents of the first sheet as CSV rows. | ||||
| 
 | ||||
| ### Windows Example | ||||
| 
 | ||||
| 0) Install dependencies. | ||||
| 
 | ||||
| <details><summary><b>Installation Notes</b> (click to show)</summary> | ||||
| 
 | ||||
| CMake and Visual Studio with "Desktop development with C++" workload must be | ||||
| installed. In addition, the following Spectre-mitigated libs must be added: | ||||
| 
 | ||||
| - MSVC C++ Spectre-mitigated libs (Latest) | ||||
| - C++ ATL for latest build tools with Spectre Mitigations | ||||
| - C++ MFC for latest build tools with Spectre Mitigations | ||||
| 
 | ||||
| The easiest way to install is to select "Individual components" and search for | ||||
| "spectre latest" (no quotation marks). Pick each option for the relevant CPU. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| 1) Set up `depot_tools`. | ||||
| 
 | ||||
| [`depot_tools.zip`](https://storage.googleapis.com/chrome-infra/depot_tools.zip) | ||||
| must be downloaded and extracted to `c:\src\depot_tools\`. | ||||
| 
 | ||||
| :::note pass | ||||
| 
 | ||||
| This ZIP has a number of hidden files and folders (including `.git`) which | ||||
| should be extracted along with the normal files. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Add the path `c:\src\depot_tools\` to the User `PATH` environment variable | ||||
| 
 | ||||
| <details><summary><b>Environment Variable Setup</b> (click to show)</summary> | ||||
| 
 | ||||
| Type `env` in the search bar and select "Edit the system environment variables". | ||||
| 
 | ||||
| In the new window, click the "Environment Variables..." button. | ||||
| 
 | ||||
| In the new window, look for the "User variables" section. Select "Path" in the | ||||
| list and click "Edit". | ||||
| 
 | ||||
| In the new window, click "New" and type `c:\src\depot_tools` and press Enter. | ||||
| 
 | ||||
| Select the row and repeatedly click "Move Up" until it is the first entry. | ||||
| 
 | ||||
| Click "OK" in each window (3 windows) and restart your computer. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| 2) Delete `c:\src\depot_tools\ninja` if it exists, then download the | ||||
| [official Windows release](https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip) | ||||
| and move the `ninja.exe` into `c:\src\depot_tools`. If a `ninja.exe` exists in | ||||
| the folder, replace the existing program. | ||||
| 
 | ||||
| 3) Make a project directory: | ||||
| 
 | ||||
| ```bash | ||||
| mkdir sheetjs-hermes | ||||
| cd sheetjs-hermes | ||||
| ``` | ||||
| 
 | ||||
| 4) Clone the `hermes-windows` repo: | ||||
| 
 | ||||
| ```bash | ||||
| git clone https://github.com/microsoft/hermes-windows | ||||
| cd hermes-windows | ||||
| git checkout c7a4a82 | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| :::note pass | ||||
| 
 | ||||
| If there are errors related to SSL or certificates or `CApath`, temporarily | ||||
| disable SSL in Git: | ||||
| 
 | ||||
| ```bash | ||||
| git config --global http.sslVerify false | ||||
| git clone https://github.com/microsoft/hermes-windows | ||||
| git config --global http.sslVerify true | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 5) Build the library: | ||||
| 
 | ||||
| ```bash | ||||
| cd hermes-windows | ||||
| .\.ado\scripts\cibuild.ps1 -AppPlatform win32 -Platform x64 -ToolsPlatform x64 | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| :::note pass | ||||
| 
 | ||||
| The script may fail with the message: | ||||
| 
 | ||||
| > cannot be loaded because running scripts is disabled on this system | ||||
| 
 | ||||
| In a "Run as Administrator" powershell window, run the following command: | ||||
| 
 | ||||
| ``` | ||||
| Set-ExecutionPolicy -ExecutionPolicy RemoteSigned | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 6) Copy every generated `.lib` and `.dll` file into the main folder: | ||||
| 
 | ||||
| ```powershell | ||||
| dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.dll" | Copy-Item -Destination .\ | ||||
| dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.lib" | Copy-Item -Destination .\ | ||||
| ``` | ||||
| 
 | ||||
| 7) Download [`sheetjs-hermes.cpp`](pathname:///hermes/sheetjs-hermesw.cpp): | ||||
| 
 | ||||
| ```bash | ||||
| curl -LO https://docs.sheetjs.com/hermes/sheetjs-hermesw.cpp | ||||
| ``` | ||||
| 
 | ||||
| 8) Build the application: | ||||
| 
 | ||||
| ```powershell | ||||
| cl /MDd sheetjs-hermesw.cpp DbgHelp.lib *.lib /I hermes-windows\API /I hermes-windows\include /I hermes-windows\public\ /I hermes-windows\API\jsi | ||||
| ``` | ||||
| 
 | ||||
| :::caution pass | ||||
| 
 | ||||
| If `cl` is not found, run the command in the "Native Tools Command Prompt" | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 9) Download the SheetJS Standalone script and the test file. Save both files in | ||||
| the project directory: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| <CodeBlock language="bash">{`\ | ||||
| curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js | ||||
| curl -LO https://sheetjs.com/pres.numbers`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| 10) Run the application: | ||||
| 
 | ||||
| ```bash | ||||
| .\sheetjs-hermesw.exe pres.numbers | ||||
| ``` | ||||
| 
 | ||||
| If successful, the program will print the library version number and the | ||||
| contents of the first sheet as CSV rows. | ||||
| 
 | ||||
| ### CLI Test | ||||
| 
 | ||||
| :::note | ||||
| @ -493,4 +676,5 @@ If successful, the script will print CSV data from the test file. | ||||
| [^2]: See ["Workbook Object"](/docs/csf/book) | ||||
| [^3]: See ["Workbook Object"](/docs/csf/book) | ||||
| [^4]: See [`sheet_to_csv` in "Utilities"](/docs/api/utilities/csv#csv-output) | ||||
| [^5]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation | ||||
| [^5]: See [`microsoft/hermes-windows`](https://github.com/microsoft/hermes-windows) on GitHub | ||||
| [^6]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation | ||||
| @ -55,7 +55,7 @@ only be used when there is no safe way to pass `ArrayBuffer` or `Uint8Array`. | ||||
| 
 | ||||
| **Byte Conventions** | ||||
| 
 | ||||
| Java has no native concept of unsigned bytes. Values in a `byte[]` are clamped | ||||
| Java has no native concept of unsigned bytes. Values in a `byte[]` are limited | ||||
| to the range `-128 .. 127`. They need to be fixed within the JS engine. | ||||
| 
 | ||||
| Some engines support typed arrays. The `Uint8Array` constructor will fix values: | ||||
|  | ||||
							
								
								
									
										117
									
								
								docz/static/hermes/sheetjs-hermesw.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										117
									
								
								docz/static/hermes/sheetjs-hermesw.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| /* sheetjs-hermesw.cpp Copyright (c) SheetJS LLC. */ | ||||
| #include <iostream> | ||||
| #include "hermes/hermes.h" | ||||
| 
 | ||||
| static char *read_file(const char *filename, size_t *sz) { | ||||
|   FILE *f = fopen(filename, "rb"); | ||||
|   if(!f) return NULL; | ||||
|   long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); } | ||||
|   char *buf = (char *)malloc(fsize * sizeof(char)); | ||||
|   *sz = fread((void *) buf, 1, fsize, f); | ||||
|   fclose(f); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* Hermes-Windows requires the null terminator */ | ||||
| static char *read_file_null(const char *filename, size_t *sz) { | ||||
|   FILE *f = fopen(filename, "rb"); | ||||
|   if(!f) return NULL; | ||||
|   long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); } | ||||
|   char *buf = (char *)malloc(fsize * sizeof(char)); | ||||
|   *sz = fread((void *) buf, 1, fsize, f); | ||||
|   buf[fsize - 1] = 0; | ||||
|   fclose(f); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| /* Unfortunately the library provides no C-friendly Buffer classes */ | ||||
| class CBuffer : public facebook::jsi::Buffer { | ||||
|   public: | ||||
|     CBuffer(const uint8_t *data, size_t size) : buf(data), sz(size) {} | ||||
|     size_t size() const override { return sz; } | ||||
|     const uint8_t *data() const override { return buf; } | ||||
| 
 | ||||
|   private: | ||||
|     const uint8_t *buf; | ||||
|     size_t sz; | ||||
| }; | ||||
| /* ArrayBuffer constructor expects MutableBuffer*/ | ||||
| class CMutableBuffer : public facebook::jsi::MutableBuffer { | ||||
|   public: | ||||
|     CMutableBuffer(uint8_t *data, size_t size) : buf(data), sz(size) {} | ||||
|     size_t size() const override { return sz; } | ||||
|     uint8_t *data() override { return buf; } | ||||
| 
 | ||||
|   private: | ||||
|     uint8_t *buf; | ||||
|     size_t sz; | ||||
| }; | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
|   std::unique_ptr<facebook::jsi::Runtime> rt(facebook::hermes::makeHermesRuntime()); | ||||
| 
 | ||||
|   /* setup */ | ||||
|   try { | ||||
|     auto src = std::make_shared<facebook::jsi::StringBuffer>( | ||||
|       "var global = (function(){ return this; }).call(null);" | ||||
|       "var console = { log: function(x) { print(x); } };" | ||||
|     ); | ||||
|     auto js = rt->prepareJavaScript(src, std::string("<eval>")); | ||||
|     rt->evaluatePreparedJavaScript(js); | ||||
|   } catch (const facebook::jsi::JSIException &e) { | ||||
|     std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n'; | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   /* load SheetJS library */ | ||||
|   try { | ||||
|     size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz); | ||||
|     auto src = std::make_shared<CBuffer>(CBuffer((uint8_t *)xlsx_full_min_js, sz)); | ||||
|     auto js = rt->prepareJavaScript(src, std::string("xlsx.full.min.js")); | ||||
|     rt->evaluatePreparedJavaScript(js); | ||||
|   } catch (const facebook::jsi::JSIException &e) { | ||||
|     std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n'; | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   /* print library version */ | ||||
|   try { | ||||
|     auto src = std::make_shared<facebook::jsi::StringBuffer>( | ||||
|       "console.log('SheetJS Library Version: ' + XLSX.version)" | ||||
|     ); | ||||
|     auto js = rt->prepareJavaScript(src, std::string("<eval>")); | ||||
|     rt->evaluatePreparedJavaScript(js); | ||||
|   } catch (const facebook::jsi::JSIException &e) { | ||||
|     std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n'; | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   try { | ||||
|     /* load payload as ArrayBuffer */ | ||||
|     size_t sz; char *data = read_file(argv[1], &sz); | ||||
|     auto payload = std::make_shared<CMutableBuffer>(CMutableBuffer((uint8_t *)data, sz)); | ||||
|     auto ab = facebook::jsi::ArrayBuffer(*rt, payload); | ||||
| 
 | ||||
|     /* define stub function to read and convert first sheet to CSV */ | ||||
|     auto src = std::make_shared<facebook::jsi::StringBuffer>( | ||||
|       "(function(buf) {" | ||||
|         "var wb = XLSX.read(buf);" | ||||
|         "return XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);" | ||||
|       "})" | ||||
|     ); | ||||
|     auto js = rt->prepareJavaScript(src, std::string("<eval>")); | ||||
|     auto func = rt->evaluatePreparedJavaScript(js); | ||||
| 
 | ||||
|     /* call stub function and capture result */ | ||||
|     auto csv = func.asObject(*rt).asFunction(*rt).call(*rt, ab); | ||||
| 
 | ||||
|     /* interpret as utf8 and print to stdout */ | ||||
|     std::string str = csv.getString(*rt).utf8(*rt); | ||||
|     std::cout << str << std::endl; | ||||
|   } catch (const facebook::jsi::JSIException &e) { | ||||
|     std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << std::endl; | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user