{"id":21605350,"url":"https://github.com/maxmouchet/julia-node-extension-demo","last_synced_at":"2025-04-11T04:03:26.672Z","repository":{"id":71203871,"uuid":"271093646","full_name":"maxmouchet/julia-node-extension-demo","owner":"maxmouchet","description":"Integrate Julia and Javascript with Node.js extensions.","archived":false,"fork":false,"pushed_at":"2020-07-29T16:29:22.000Z","size":215,"stargazers_count":29,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-05T01:01:50.198Z","etag":null,"topics":["julia","node-addon-api","nodejs"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxmouchet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-09T19:38:57.000Z","updated_at":"2024-07-06T04:42:58.000Z","dependencies_parsed_at":"2023-02-22T16:16:13.909Z","dependency_job_id":null,"html_url":"https://github.com/maxmouchet/julia-node-extension-demo","commit_stats":{"total_commits":41,"total_committers":1,"mean_commits":41.0,"dds":0.0,"last_synced_commit":"ccfa5499cc5677a68fef4dbb2f00a6789dcf2db6"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmouchet%2Fjulia-node-extension-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmouchet%2Fjulia-node-extension-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmouchet%2Fjulia-node-extension-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmouchet%2Fjulia-node-extension-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxmouchet","download_url":"https://codeload.github.com/maxmouchet/julia-node-extension-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248018050,"owners_count":21034047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["julia","node-addon-api","nodejs"],"created_at":"2024-11-24T20:13:00.202Z","updated_at":"2025-04-11T04:03:26.651Z","avatar_url":"https://github.com/maxmouchet.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Integrate Julia and Javascript with Node.js extensions\n\n[![CI](https://github.com/maxmouchet/julia-node-extension-demo/workflows/CI/badge.svg)](https://github.com/maxmouchet/julia-node-extension-demo/actions?query=workflow%3ACI)\n[![Publish](https://github.com/maxmouchet/julia-node-extension-demo/workflows/Publish/badge.svg)](https://github.com/maxmouchet/julia-node-extension-demo/actions?query=workflow%3APublish)\n[![npm](https://img.shields.io/npm/v/@maxmouchet/julia-node-extension-demo)](https://www.npmjs.com/package/@maxmouchet/julia-node-extension-demo)\n[![JuliaCon 2020](https://img.shields.io/badge/Talk-JuliaCon%202020-761c7c)](https://pretalx.com/juliacon2020/talk/Q88P8U/)\n\nThis repository shows how to build a Node.js native extension that calls Julia code from a precompiled system image.\nFor an introduction in video, see the [JuliaCon 2020 talk](https://pretalx.com/juliacon2020/talk/Q88P8U/).\n\n[Overview](#overview)\n• [Requirements](#requirements)\n• [Running the extension](#running-the-extension)\n• [Building the extension](#building-the-extension)\n• [Resources](#resources)\n\n## Overview\n\nIn this repository we consider the following use case:\n- You have an algorithm written in Julia, and you want to use this algorithm in a Node.js environment.  \n- You can't or you don't want to install Julia on your servers.  \n- You want to avoid Julia compilation costs and you want to share data efficiently between the Julia and Node.js runtimes.\n\nTo achieve this goal, we propose a two-step approach:\n1. Build a Julia system image which includes your precompiled code.\n2. Build a Node.js native extension in C/C++ which glues together the Julia and Node.js runtimes.\n\nThe main drawbacks of this approach are:\n- It requires to write C/C++ glue code.\n- Changes to the Julia code requires re-building the system image, and (potentially) adapting the C/C++ code.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/assets/binding.png\" alt=\"N-API diagram\" width=\"800px\"/\u003e\u003cbr/\u003e\n  The main goal of the Node.js extension is to convert between Julia and Node.js data types.\n\u003c/p\u003e\n\n\u003c!-- This approach is similar to [pyjulia](https://github.com/JuliaPy/pyjulia) for Python or [JuliaCall](https://cran.r-project.org/web/packages/JuliaCall/index.html) for R, with the addition of the system image. --\u003e\n\nWe use the following tools:\n- [PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl) to build the Julia system image.\n- [node-addon-api](https://github.com/nodejs/node-addon-api) a C++ wrapper of [N-API](https://nodejs.org/dist/latest/docs/api/n-api.html) to write the Node.js extension.\n- [node-gyp](https://github.com/nodejs/node-gyp) to build the extension.\n- [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to package and distribute the extension.\n\n### Repository structure\n\n```bash\n\n├── .github\n│   └── workflows      # GitHub workflows for testing and distribution\n├── binding.gyp        # Build system configuration\n├── example            # Example Express API\n│   ├── app.js           # Server\n│   └── test.js          # Client\n├── index.js           # Extension loader\n├── julia              # Julia system image\n│   ├── build.jl         # System image build script\n│   └── Clustering.jl    # Target package\n├── node               # Node.js extension\n│   ├── binding.cc       # Extension code\n│   ├── extra.h          # Helpers for the Julia C API\n│   └── init.h           # Helpers for Julia initialization\n└── test.js            # Extension test\n```\n\n## Requirements\n\n- Node.js v10.16+ ([N-API v4](https://nodejs.org/api/n-api.html#n_api_n_api_version_matrix))\n- Julia v1.4 (only for building the extension)\n- x86-64 Linux or macOS; Windows is not (yet) supported due to build issues (PR are welcome!)\n\n## Running the extension\n\n### Installation\n\n```bash\n# Requires Node v10.16+ (N-API \u003e= 4).\n# Windows is not supported (yet).\n\n# Pre-built binaries are avaiable for Linux and macOS (x86-64).\n# If you are on a different architecture, node-pre-gyp will trigger a build.\nnpm install @maxmouchet/julia-node-extension-demo\n```\n\n### Example\n\n```js\nconst clustering = require('@maxmouchet/julia-node-extension-demo')\n// X: dxn matrix (n d-dimensional data points) in column-major order\n// k: number of clusters\nclustering.kmeans(X: Float64Array, d: Number, k: Number)\n```\n\nSee [test.js](test.js) and [example/](example/) for more complete examples.\n\n## Building the extension\n\n```bash\nnpm install node-pre-gyp\n\n# Run build.jl and compile binding.cc\n# =\u003e dist/linux-x64-napi-v4/binding.node\n./node_modules/node-pre-gyp/bin/node-pre-gyp build\n\n# Package everything together\n# =\u003e build/stage/julia-node-extension-demo/vx.y.z/Release/linux-x64-napi-v4.tar.gz\n./node_modules/node-pre-gyp/bin/node-pre-gyp package\n\n# Upload the package to Amazon S3\n./node_modules/node-pre-gyp/bin/node-pre-gyp publish\n```\n\n## Resources\n\n- [Julia Documentation: Embedding](https://docs.julialang.org/en/v1/manual/embedding/)\n- [julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h) and [jlapi.c](https://github.com/JuliaLang/julia/blob/master/src/jlapi.c) source files to browse the Julia C API.\n- [node-addon-api usage with node-gyp](https://github.com/nodejs/node-addon-api/blob/master/doc/node-gyp.md)\n- [node-pre-gyp documentation](https://github.com/mapbox/node-pre-gyp)\n- [julia #32614 - Make it easier for embedded Julia to use a custom system image](https://github.com/JuliaLang/julia/issues/32614)\n- [julia #28886 - Test and document embedding with dynamically loaded libjulia.](https://github.com/JuliaLang/julia/pull/28886)\n\n## Project Status\n\nThe package is tested against Julia 1.4 and Node.js v10/v14, on Ubuntu and macOS.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmouchet%2Fjulia-node-extension-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxmouchet%2Fjulia-node-extension-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmouchet%2Fjulia-node-extension-demo/lists"}