Christa  Stehr

Christa Stehr


Mastering Laravel in Arabic #017 - Include Sidebar And Navbar

Include Sidebar And Navbar


What is GEEK

Buddha Community

Mastering Laravel in Arabic #017 - Include Sidebar And Navbar
Seamus  Quitzon

Seamus Quitzon


Php how to delete multiple rows through checkbox using ajax in laravel

First thing, we will need a table and i am creating products table for this example. So run the following query to create table.

CREATE TABLE `products` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
 `description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
 `updated_at` datetime DEFAULT NULL,

Next, we will need to insert some dummy records in this table that will be deleted.

INSERT INTO `products` (`name`, `description`) VALUES

('Test product 1', 'Product description example1'),

('Test product 2', 'Product description example2'),

('Test product 3', 'Product description example3'),

('Test product 4', 'Product description example4'),

('Test product 5', 'Product description example5');

Now we are redy to create a model corresponding to this products table. Here we will create Product model. So let’s create a model file Product.php file under app directory and put the code below.


namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
    protected $fillable = [

Step 2: Create Route

Now, in this second step we will create some routes to handle the request for this example. So opeen routes/web.php file and copy the routes as given below.


Route::get('product', 'ProductController@index');
Route::delete('product/{id}', ['as'=>'product.destroy','uses'=>'ProductController@destroy']);
Route::delete('delete-multiple-product', ['as'=>'product.multiple-delete','uses'=>'ProductController@deleteMultiple']);

#laravel #delete multiple rows in laravel using ajax #laravel ajax delete #laravel ajax multiple checkbox delete #laravel delete multiple rows #laravel delete records using ajax #laravel multiple checkbox delete rows #laravel multiple delete

Abdullah  Kozey

Abdullah Kozey


Extending JAX with custom C++ and CUDA code

Extending JAX with custom C++ and CUDA code


This repository is meant as a tutorial demonstrating the infrastructure required to provide custom ops in JAX when you have an existing implementation in C++ and, optionally, CUDA. I originally wanted to write this as a blog post, but there's enough boilerplate code that I ended up deciding that it made more sense to just share it as a repo with the tutorial in the README, so here we are!

The motivation for this is that in my work I want to use libraries like JAX to fit models to data in astrophysics. In these models, there is often at least one part of the model specification that is physically motivated and while there are generally existing implementations of these model elements, it is often inefficient or impractical to re-implement these as a high-level JAX function. Instead, I want to expose a well-tested and optimized implementation in C directly to JAX. In my work, this often includes things like iterative algorithms or special functions that are not well suited to implementation using JAX directly.

So, as part of updating my exoplanet library to interface with JAX, I had to learn what infrastructure was required to support this use case, and since I couldn't find a tutorial that covered all the pieces that I needed in one place, I wanted to put this together. Pretty much everything that I'll talk about is covered in more detail somewhere else (even if that somewhere is just a comment in some source code), but hopefully this summary can point you in the right direction if you have a use case like this.

A warning: I'm writing this in January 2021 and much of what I'm talking about is based on essentially undocumented APIs that are likely to change. Furthermore, I'm not affiliated with the JAX project and I'm far from an expert so I'm sure there are wrong things that I say. I'll try to update this if I notice things changing or if I learn of issues, but no promises! So, MIT license and all that: use at your own risk.

Related reading

As I mentioned previously, this tutorial is built on a lot of existing literature and I won't reproduce all the details of those documents here, so I wanted to start by listing the key resources that I found useful:

The How primitives work tutorial in the JAX documentation includes almost all the details about how to expose a custom op to JAX and spending some quality time with that tutorial is not wasted time. The only thing missing from that document is a description of how to use the XLA CustomCall interface.

Which brings us to the XLA custom calls documentation. This page is pretty telegraphic, but it includes a description of the interface that your custom call functions need to support. In particular, this is where the differences in interface between the CPU and GPU are described, including things like the "opaque" parameter and how multiple outputs are handled.

I originally learned how to write the pybind11 interface for an XLA custom call from the danieljtait/jax_xla_adventures repository by Dan Tait on GitHub. Again, this doesn't include very many details, but that's really a benefit here because it really distills the infrastructure to a place where I could understand what was going on.

Finally, much of what I know about this topic, I learned from spelunking in the jaxlib source code on GitHub. That code is pretty readable and includes good comments most of the time so that's a good place to look if you get stuck since folks there might have already faced the issue.

What is an "op"

In frameworks like JAX (or Theano, or TensorFlow, or PyTorch, to name a few), models are defined as a collection of operations or "ops" that can be chained, fused, or differentiated in clever ways. For our purposes, an op defines a function that knows:

  1. how the input and output parameter shapes and types are related,
  2. how to compute the output from a set of inputs, and
  3. how to propagate derivatives using the chain rule.

There are a lot of choices about where you draw the lines around a single op and there will be tradeoffs in terms of performance, generality, ease of use, and other factors when making these decisions. In my experience, it is often best to define the minimal scope ops and then allow your framework of choice to combine it efficiently with the rest of your model, but there will always be counter examples.

Our example application: solving Kepler's equation

In this section I'll describe the application presented in this project. Feel free to skip this if you just want to get to the technical details.

This project exposes a single jit-able and differentiable JAX operation to solve Kepler's equation, a tool that is used for computing gravitational orbits in astronomy. This is basically the "hello world" example that I use whenever learning about something like this. For example, I have previously written about how to expose such an op when using Stan. The implementation used in that post and the one used here are not meant to be the most robust or efficient, but it is relatively simple and it exposes some of the interesting issues that one might face when writing custom JAX ops. If you're interested in the mathematical details, take a look at my blog post, but the key point for now is that this operation involves solving a transcendental equation, and in this tutorial we'll use a simple iterative method that you'll find in the kepler.h header file. Then, the derivatives of this operation can be evaluated using implicit differentiation. Unlike in the previously mentioned blog post, our operation will actually return the sine and cosine of the eccentric anomaly, since that's what most high performance versions of this function would return and because the way XLA handles ops with multiple outputs is a little funky.

The cost/benefit analysis

One important question to answer first is: "should I actually write a custom JAX extension?" If you're here, you've probably already thought about that, but I wanted to emphasize a few points to consider.

Performance: The main reason why you might want to implement a custom op for JAX is performance. JAX's JIT compiler can get great performance in a broad range of applications, but for some of the problems I work on, finely-tuned C++ can be much faster. In my experience, iterative algorithms, other special functions, or code with complicated logic are all examples of places where a custom op might greatly improve performance. I'm not always good at doing this, but it's probably worth benchmarking performance of a version of your code implemented directly in high-level JAX against your custom op.

Autodiff: One thing that is important to realize is that the extension that we write won't magically know how to propagate derivatives. Instead, we'll be required to provide a JAX interface for applying the chain rule to out op. In other words, if you're setting out to wrap that huge Fortran library that has been passed down through the generations, the payoff might not be as great as you hoped unless (a) the code already provides operations for propagating derivatives (in which case you JAX op probably won't support second and higher order differentiation), or (b) you can easily compute the differentiation rules using the algorithm that you already have (which is the case we have for our example application here). In my work, I try (sometimes unsuccessfully) to identify the minimum number and size of ops that I can get away with and then implement most of my models directly in JAX. In our demo application, for example, I could have chosen to make an XLA op generating a full radial velocity model, instead of just solving Kepler's equation, and that might (or might not) give better performance. But, the differentiation rules are much simpler the way it is implemented.

Summary of the relevant files

The files in this repo come in three categories:

In the root directory, there are the standard packaging files like a and pyproject.toml. Most of this setup is pretty standard, but I'll highlight some of the unique elements in the packaging section below. For example, we'll use a slightly strange combination of PEP-517/518 and CMake to build the extensions. This isn't strictly necessary, but it's the easiest packaging setup that I've been able to put together.

Next, the src/kepler_jax directory is a Python module with the definition of our JAX primitive roughly following the JAX How primitives work tutorial.

Finally, the C++ and CUDA code implementing our XLA op live in the lib directory. The pybind11_kernel_helpers.h and kernel_helpers.h headers are boilerplate necessary for building in the interface. The rest of the files include the code specific for this implementation, but I'll describe this in more detail below.

Defining an XLA custom call on the CPU

The algorithm for our example problem is is implemented in the lib/kepler.h header and I won't go into details about the algorithm here, but the main point is that this could be an implementation built on any external library that you can call from C++ and, if you want to support GPU usage, CUDA. That header file includes a single function compute_eccentric_anomaly with the following signature:

template <typename T>
void compute_eccentric_anomaly(
   const T& mean_anom, const T& ecc, T* sin_ecc_anom, T* cos_ecc_anom

This is the function that we want to expose to JAX.

As described in the XLA documentation, the signature for a CPU XLA custom call in C++ is:

void custom_call(void* out, const void** in);

where, as you might expect, the elements of in point to the input values. So, in our case, the inputs are an integer giving the dimension of the problem size, an array with the mean anomalies mean_anomaly, and an array of eccentricities ecc. Therefore, we might parse the input as follows:

#include <cstdint>  // int64_t

template <typename T>
void cpu_kepler(void *out, const void **in) {
  const std::int64_t size = *reinterpret_cast<const std::int64_t *>(in[0]);
  const T *mean_anom = reinterpret_cast<const T *>(in[1]);
  const T *ecc = reinterpret_cast<const T *>(in[2]);

Here we have used a template so that we can support both single and double precision version of the op.

The output parameter is somewhat more complicated. If your op only has one output, you would access it using

T *result = reinterpret_cast<T *>(out);

but when you have multiple outputs, things get a little hairy. In our example, we have two outputs, the sine sin_ecc_anom and cosine cos_ecc_anom of the eccentric anomaly. Therefore, our out parameter -- even though it looks like a void* -- is actually a void**! Therefore, we will access the output as follows:

template <typename T>
void cpu_kepler(void *out_tuple, const void **in) {
  // ...
  void **out = reinterpret_cast<void **>(out_tuple);
  T *sin_ecc_anom = reinterpret_cast<T *>(out[0]);
  T *cos_ecc_anom = reinterpret_cast<T *>(out[1]);

Then finally, we actually apply the op and the full implementation, which you can find in lib/ is:

// lib/
#include <cstdint>

template <typename T>
void cpu_kepler(void *out_tuple, const void **in) {
  const std::int64_t size = *reinterpret_cast<const std::int64_t *>(in[0]);
  const T *mean_anom = reinterpret_cast<const T *>(in[1]);
  const T *ecc = reinterpret_cast<const T *>(in[2]);

  void **out = reinterpret_cast<void **>(out_tuple);
  T *sin_ecc_anom = reinterpret_cast<T *>(out[0]);
  T *cos_ecc_anom = reinterpret_cast<T *>(out[1]);

  for (std::int64_t n = 0; n < size; ++n) {
    compute_eccentric_anomaly(mean_anom[n], ecc[n], sin_ecc_anom + n, cos_ecc_anom + n);

and that's it!

Building & packaging for the CPU

Now that we have an implementation of our XLA custom call target, we need to expose it to JAX. This is done by compiling a CPython module that wraps this function as a PyCapsule type. This can be done using pybind11, Cython, SWIG, or the Python C API directly, but for this example we'll use pybind11 since that's what I'm most familiar with. The LAPACK ops in jaxlib are implemented using Cython if you'd like to see an example of how to do that.

Another choice that I've made is to use CMake to build the extensions. It would be totally possible (and perhaps preferable if you only support CPU usage) to stick to just using setuptools directly, but setuptools doesn't seem to have great support for compiling CUDA extensions so that's why I settled on CMake. In the end, it's not too painful since CMake can be included as a build dependency in pyproject.toml so users won't have to install it separately. Another build option would be to use bazel to compile the code, like the JAX project, but I don't have any experience with it so I decided to stick with what I know. The key point is that we're just compiling a regular old Python module so you can use whatever infrastructure you're familiar with!

With these choices out of the way, the boilerplate code required to define the interface is, using the cpu_kepler function defined in the previous section as follows:

// lib/
#include <pybind11/pybind11.h>

// If you're looking for it, this function is actually implemented in
// lib/pybind11_kernel_helpers.h
template <typename T>
pybind11::capsule EncapsulateFunction(T* fn) {
  return pybind11::capsule((void*)fn, "xla._CUSTOM_CALL_TARGET");

pybind11::dict Registrations() {
  pybind11::dict dict;
  dict["cpu_kepler_f32"] = EncapsulateFunction(cpu_kepler<float>);
  dict["cpu_kepler_f64"] = EncapsulateFunction(cpu_kepler<double>);
  return dict;

PYBIND11_MODULE(cpu_ops, m) { m.def("registrations", &Registrations); }

In this case, we're exporting a separate function for both single and double precision. Another option would be to pass the data type to the function and perform the dispatch logic directly in C++, but I find it cleaner to do it like this.

With that out of the way, the actual build routine is defined in the following files:

In ./pyproject.toml, we specify that pybind11 and cmake are required build dependencies and that we'll use setuptools.build_meta as the build backend. is a pretty typical setup file with a custom class for building the extensions that executes CMake for the actual compilation step. This does include some extra configuration arguments for CMake to make sure that it uses the correct Python libraries and installs the compiled objects to the right place. It might be possible to use something like scikit-build to replace this step, but I struggled to get it working.

Finally, CMakeLists.txt defines the build process for CMake using pybind11's support for CMake builds. This will also, optionally, build the GPU ops as discussed below.

With these files in place, we can now compile our XLA custom call ops using

pip install .

The final thing that I wanted to reiterate in this section is that kepler_jax.cpu_ops is just a regular old CPython extension module, so anything that you already know about packaging C extensions or any other resources that you can find on that topic can be applied. This wasn't obvious when I first started learning about this so I definitely went down some rabbit holes that hopefully you can avoid.

Exposing this op as a JAX primitive

The main components that are required to now call our custom op from JAX are well covered by the How primitives work tutorial, so I won't reproduce all of that here. Instead I'll summarize the key points and then provide the missing part. If you haven't already, you should definitely read that tutorial before getting started on this part.

In summary, we will define a jax.core.Primitive object with an "abstract evaluation" rule (see src/kepler_jax/ for all the details) following the primitives tutorial. Then, we'll add a "translation rule" and a "JVP rule". We're lucky in this case, and we don't need to add a "transpose rule". JAX can actually work that out automatically, since our primitive is not itself used in the calculation of the output tangents. This won't always be true, and the How primitives work tutorial includes an example of what to do in that case.

Before defining these rules, we need to register the custom call target with JAX. To do that, we import our compiled cpu_ops extension module from above and use the registrations dictionary that we defined:

from jax.lib import xla_client
from kepler_jax import cpu_ops

for _name, _value in cpu_ops.registrations().items():
    xla_client.register_cpu_custom_call_target(_name, _value)

Then, the translation rule is defined roughly as follows (the one you'll find in the source code is a little more complicated since it supports both CPU and GPU translation):

# src/kepler_jax/
import numpy as np

def _kepler_cpu_translation(c, mean_anom, ecc):
    # The inputs have "shapes" that provide both the shape and the dtype
    mean_anom_shape = c.get_shape(mean_anom)
    ecc_shape = c.get_shape(ecc)

    # Extract the dtype and shape
    dtype = mean_anom_shape.element_type()
    dims = mean_anom_shape.dimensions()
    assert ecc_shape.element_type() == dtype
    assert ecc_shape.dimensions() == dims

    # The total size of the input is the product across dimensions
    size =

    # The inputs and outputs all have the same shape so let's predefine this
    # specification
    shape = xla_client.Shape.array_shape(
        np.dtype(dtype), dims, tuple(range(len(dims) - 1, -1, -1))

    # We dispatch a different call depending on the dtype
    if dtype == np.float32:
        op_name = b"cpu_kepler_f32"
    elif dtype == np.float64:
        op_name = b"cpu_kepler_f64"
        raise NotImplementedError(f"Unsupported dtype {dtype}")

    # On the CPU, we pass the size of the data as a the first input
    # argument
    return xla_client.ops.CustomCallWithLayout(
        # The inputs:
        operands=(xla_client.ops.ConstantLiteral(c, size), mean_anom, ecc),
        # The input shapes:
              xla_client.Shape.array_shape(np.dtype(np.int64), (), ()),
        # The output shapes:
        shape_with_layout=xla_client.Shape.tuple_shape((shape, shape)),

xla.backend_specific_translations["cpu"][_kepler_prim] = _kepler_cpu_translation

There appears to be a lot going on here, but most of it is just typechecking. The main meat of it is the CustomCallWithLayout function which, as far as I can tell, isn't documented anywhere. Here's a summary of its arguments, as best as I can tell:

The first argument is the XLA builder that you were passed when your translation rule was called.

The second argument is the name (as bytes!) that you gave your PyCapsule in the registrations dictionary in lib/ You can check what names your capsules had by looking at cpu_ops.registrations().keys().

Then, the following arguments give the input arguments, and the "shapes" of the input and output arrays. In this context, a "shape" is specified by a data type, a tuple defining the size of each dimension (what I would normally call the shape), and a tuple defining the dimension order. In this case, we're requiring that all of our inputs and outputs are of the same "shape".

It's worth remembering that we're expecting the first argument to our function to be the size of the arrays, and you'll see that that is included as a ConstantLiteral parameter (explicitly cast to int64).

I'm not going to talk about the JVP rule here since it's quite problem specific, but I've tried to comment the code reasonably thoroughly so check out the code in src/kepler_jax/ if you're interested, and open an issue if anything isn't clear.

Defining an XLA custom call on the GPU

The custom call on the GPU isn't terribly different from the CPU version above, but the syntax is somewhat different and there's a heck of a lot more boilerplate required. Since we need to compile and link CUDA code, there are also a few more packaging steps, but we'll get to that in the next section. The description in this section is a little all over the place, but the key files to look at to get more info are (a) lib/ for the dispatch functions called from Python, and (b) lib/ for the CUDA code implementing the kernel.

The signature for the GPU custom call is:

// lib/
template <typename T>
void gpu_kepler(
  cudaStream_t stream, void **buffers, const char *opaque, std::size_t opaque_len

The first parameter is a CUDA stream, which I won't talk about at all because I don't really know very much about GPU programming and we don't really need to worry about it for now. Then you'll notice that the inputs and outputs are all provided as a single void** buffer. These will be ordered such that our access code from above is replaced by:

// lib/
template <typename T>
void gpu_kepler(
  cudaStream_t stream, void **buffers, const char *opaque, std::size_t opaque_len
) {
  const T *mean_anom = reinterpret_cast<const T *>(buffers[0]);
  const T *ecc = reinterpret_cast<const T *>(buffers[1]);
  T *sin_ecc_anom = reinterpret_cast<T *>(buffers[2]);
  T *cos_ecc_anom = reinterpret_cast<T *>(buffers[3]);

where you might notice that the size parameter is no longer one of the inputs. Instead the array size is passed using the opaque parameter since its value is required on the CPU and within the GPU kernel (see the XLA custom calls documentation for more details). To use this opaque parameter, we will define a type to hold size:

// lib/kernels.h
struct KeplerDescriptor {
  std::int64_t size;

and then the following boilerplate to serialize it:

// lib/kernel_helpers.h
#include <string>

// Note that bit_cast is only available in recent C++ standards so you might need
// to provide a shim like the one in lib/kernel_helpers.h
template <typename T>
std::string PackDescriptorAsString(const T& descriptor) {
  return std::string(bit_cast<const char*>(&descriptor), sizeof(T));

// lib/pybind11_kernel_helpers.h
#include <pybind11/pybind11.h>

template <typename T>
pybind11::bytes PackDescriptor(const T& descriptor) {
  return pybind11::bytes(PackDescriptorAsString(descriptor));

This serialization procedure should then be exposed in the Python module using:

// lib/
#include <pybind11/pybind11.h>

PYBIND11_MODULE(gpu_ops, m) {
  // ...
        [](std::int64_t size) {
          return PackDescriptor(KeplerDescriptor{size});

Then, to deserialize this descriptor, we can use the following procedure:

// lib/kernel_helpers.h
template <typename T>
const T* UnpackDescriptor(const char* opaque, std::size_t opaque_len) {
  if (opaque_len != sizeof(T)) {
    throw std::runtime_error("Invalid opaque object size");
  return bit_cast<const T*>(opaque);

// lib/
template <typename T>
void gpu_kepler(
  cudaStream_t stream, void **buffers, const char *opaque, std::size_t opaque_len
) {
  // ...
  const KeplerDescriptor &d = *UnpackDescriptor<KeplerDescriptor>(opaque, opaque_len);
  const std::int64_t size = d.size;

Once we have these parameters, the full procedure for launching the CUDA kernel is:

// lib/
template <typename T>
void gpu_kepler(
  cudaStream_t stream, void **buffers, const char *opaque, std::size_t opaque_len
) {
  const T *mean_anom = reinterpret_cast<const T *>(buffers[0]);
  const T *ecc = reinterpret_cast<const T *>(buffers[1]);
  T *sin_ecc_anom = reinterpret_cast<T *>(buffers[2]);
  T *cos_ecc_anom = reinterpret_cast<T *>(buffers[3]);
  const KeplerDescriptor &d = *UnpackDescriptor<KeplerDescriptor>(opaque, opaque_len);
  const std::int64_t size = d.size;

  // Select block sizes, etc., no promises that these numbers are the right choices
  const int block_dim = 128;
  const int grid_dim = std::min<int>(1024, (size + block_dim - 1) / block_dim);

  // Launch the kernel
      <<<grid_dim, block_dim, 0, stream>>>(size, mean_anom, ecc, sin_ecc_anom, cos_ecc_anom);

  cudaError_t error = cudaGetLastError();
  if (error != cudaSuccess) {
    throw std::runtime_error(cudaGetErrorString(error));

Finally, the kernel itself is relatively simple:

// lib/
template <typename T>
__global__ void kepler_kernel(
  std::int64_t size, const T *mean_anom, const T *ecc, T *sin_ecc_anom, T *cos_ecc_anom
) {
  for (std::int64_t idx = blockIdx.x * blockDim.x + threadIdx.x; idx < size;
       idx += blockDim.x * gridDim.x) {
    compute_eccentric_anomaly<T>(mean_anom[idx], ecc[idx], sin_ecc_anom + idx, cos_ecc_anom + idx);

Building & packaging for the GPU

Since we're already using CMake to build our project, it's not too hard to add support for CUDA. I've chosen to enable GPU builds by the environment variable KEPLER_JAX_CUDA=yes that you'll see in both and CMakeLists.txt. Other than conditionally adding an Extension in, everything else on the Python side is the same. In CMakeLists.txt, we also add a conditional:

  # ...
  message(STATUS "Building without CUDA")

Then, to expose this to JAX, we need to update the translation rule from above as follows:

# src/kepler_jax/
import numpy as np
from jax.lib import xla_client
from kepler_jax import gpu_ops

for _name, _value in gpu_ops.registrations().items():
    xla_client.register_custom_call_target(_name, _value, platform="gpu")

def _kepler_gpu_translation(c, mean_anom, ecc):
    # Most of this function is the same as the CPU version above...

    # The name of the op is now prefaced with 'gpu' (our choice, see lib/,
    # not a requirement)
    if dtype == np.float32:
        op_name = b"gpu_kepler_f32"
    elif dtype == np.float64:
        op_name = b"gpu_kepler_f64"
        raise NotImplementedError(f"Unsupported dtype {dtype}")

    # We need to serialize the array size using a descriptor
    opaque = gpu_ops.build_kepler_descriptor(size)

    # The syntax is *almost* the same as the CPU version, but we need to pass the
    # size using 'opaque' rather than as an input
    return xla_client.ops.CustomCallWithLayout(
        operands=(mean_anom, ecc),
        operand_shapes_with_layout=(shape, shape),
        shape_with_layout=xla_client.Shape.tuple_shape((shape, shape)),

xla.backend_specific_translations["gpu"][_kepler_prim] = _kepler_gpu_translation

Otherwise, everything else from our CPU implementation doesn't need to change.


As usual, you should always test your code and this repo includes some unit tests in the tests directory for inspiration. You can also see an example of how to run these tests using the GitHub Actions CI service and the workflow in .github/workflows/tests.yml. I don't know of any public CI servers that provide GPU support, but I do include a test to confirm that the GPU ops can be compiled. You can see the infrastructure for that test in the .github/action directory.

See this in action

To demo the use of this custom op, I put together a notebook, based on an example from the exoplanet docs. You can see this notebook in the demo.ipynb file in the root of this repository or open it on Google Colab:

Open In Colab


Author: dfm
Source Code:
License: MIT License


Joel  Hawkins

Joel Hawkins


Elk: A Low Footprint JavaScript Engine for Embedded Systems

Elk: a tiny JS engine for embedded systems

Elk is a tiny embeddable JavaScript engine that implements a small but usable subset of ES6. It is designed for microcontroller development. Instead of writing firmware code in C/C++, Elk allows to develop in JavaScript. Another use case is providing customers with a secure, protected scripting environment for product customisation.

Elk features include:

  • Cross platform. Works anywhere from 8-bit microcontrollers to 64-bit servers
  • Zero dependencies. Builds cleanly by ISO C or ISO C++ compilers
  • Easy to embed: just copy elk.c and elk.h to your source tree
  • Very small and simple embedding API
  • Can call native C/C++ functions from JavaScript and vice versa
  • Does not use malloc. Operates with a given memory buffer only
  • Small footprint: about 20KB on flash/disk, about 100 bytes RAM for core VM
  • No bytecode. Interprets JS code directly

Below is a demonstration on a classic Arduino Nano board which has 2K RAM and 30K flash (see full sketch):

Elk on Arduino Nano

JavaScript on ESP32

The Esp32JS Arduino sketch is an example of Elk integration with ESP32. Flash this sketch on your ESP32 board, go to, and get a JavaScript development environment instantly! Reloading your script takes a fraction of a second - compare that with a regular reflashing.. Here how it looks like:

The example JS firmware implements:

  • Blinks an LED periodically
  • Connects to the HiveMQ MQTT server
  • Subscribes to the elk/rx topic
  • When an MQTT message is received, sends some stats to the elk/tx topic:

That's screenshot is taken from the MQTT server which shows that we sent a hello JS! message and received stats in response:

Call JavaScript from C

#include <stdio.h>
#include "elk.h"

int main(void) {
  char mem[200];
  struct js *js = js_create(mem, sizeof(mem));  // Create JS instance
  jsval_t v = js_eval(js, "1 + 2 * 3", ~0);     // Execute JS code
  printf("result: %s\n", js_str(js, v));        // result: 7
  return 0;

Call C from JavaScript

This demonstrates how JS code can import and call existing C functions:

#include <stdio.h>
#include "elk.h"

// C function that adds two numbers. Will be called from JS
int sum(int a, int b) {
  return a + b;

int main(void) {
  char mem[200];
  struct js *js = js_create(mem, sizeof(mem));  // Create JS instance
  jsval_t v = js_import(js, sum, "iii");        // Import C function "sum"
  js_set(js, js_glob(js), "f", v);              // Under the name "f"
  jsval_t result = js_eval(js, "f(3, 4);", ~0); // Call "f"
  printf("result: %s\n", js_str(js, result));   // result: 7
  return 0;

Supported features

  • Operations: all standard JS operations except:
    • !=, ==. Use strict comparison !==, ===
    • No ternary operator a ? b : c
    • No computed member access a[b]
  • Typeof: typeof('a') === 'string'
  • While: while (...) { ... }
  • Conditional: if (...) ... else ...
  • Simple types: let a, b, c = 12.3, d = 'a', e = null, f = true, g = false;
  • Functions: let f = function(x, y) { return x + y; };
  • Objects: let obj = {f: function(x) { return x * 2}}; obj.f(3);
  • Every statement must end with a semicolon ;
  • Strings are binary data chunks, not Unicode strings: 'Київ'.length === 8

Not supported features

  • No var, no const. Use let (strict mode only)
  • No do, switch, for. Use while
  • No => functions. Use let f = function(...) {...};
  • No arrays, closures, prototypes, this, new, delete
  • No standard library: no Date, Regexp, Function, String, Number


Since Elk parses and interprets JS code on the fly, it is not meant to be used in a performance-critical scenarios. For example, below are the numbers for a simple loop code on a different architectures.

let a = 0;        // 97 milliseconds on a 16Mhz 8-bit Atmega328P (Arduino Uno and alike)
while (a < 100)   // 16 milliseconds on a 48Mhz SAMD21
  a++;            //  5 milliseconds on a 133Mhz Raspberry RP2040
                  //  2 milliseconds on a 240Mhz ESP32

Build options

Available preprocessor definitions:

JS_EXPR_MAX20Maximum tokens in expression. Expression evaluation function declares an on-stack array jsval_t stk[JS_EXPR_MAX];. Increase to allow very long expressions. Reduce to save C stack space.
JS_DUMPundefinedDefine to enable js_dump(struct js *) function which prints JS memory internals to stdout

Note: on ESP32 or ESP8266, compiled functions go into the .text ELF section and subsequently into the IRAM MCU memory. It is possible to save IRAM space by copying Elk code into the irom section before linking. First, compile the object file, then rename .text section, e.g. for ESP32:

$ xtensa-esp32-elf-gcc $CFLAGS elk.c -c elk.tmp
$ xtensa-esp32-elf-objcopy --rename-section .text=.irom0.text elk.tmp elk.o

API reference


struct js *js_create(void *buf, size_t len);

Initialize JS engine in a given memory block. Elk will only use that memory block to hold its runtime, and never use any extra memory. Return: a non-NULL opaque pointer on success, or NULL when len is too small. The minimum len is about 100 bytes.

The given memory buffer is laid out in the following way:

  | <-------------------------------- len ------------------------------> |
  | struct js, ~100 bytes  |   runtime vars    |    free memory           | 


jsval_t js_eval(struct js *, const char *buf, size_t len);

Evaluate JS code in buf, len and return result of the evaluation. During the evaluation, Elk stores variables in the "runtime" memory section. When js_eval() returns, Elk does not keep any reference to the evaluated code: all strings, functions, etc, are copied to the runtime.

Important note: the returned result is valid only before the next call to js_eval(). The reason is that js_eval() triggers a garbage collection. A garbage collection is mark-and-sweep, run before every top-level statement gets executed.

The runtime footprint is as follows:

  • An empty object is 8 bytes
  • Each object property is 16 bytes
  • A string is 4 bytes + string length, aligned to 4 byte boundary
  • A C stack usage is ~200 bytes per nested expression evaluation


const char *js_str(struct js *, jsval_t val);

Stringify JS value val and return a pointer to a 0-terminated result. The string is allocated in the "free" memory section. If there is no enough space there, an empty string is returned. The returned pointer is valid until the next js_eval() call.


jsval_t js_import(struct js *js, uintptr_t funcaddr, const char *signature);

Import an existing C function with address funcaddr and signature signature. Return imported function, suitable for subsequent js_set().

  • js: JS instance
  • funcaddr: C function address: (uintptr_t) &my_function
  • signature: specifies C function signature that tells how JS engine should marshal JS arguments to the C function. First letter specifies return value type, following letters - parameters:
    • b: a C bool type
    • d: a C double type
    • i: a C integer type: char, short, int, long
    • s: a C string, a 0-terminated char *
    • j: a jsval_t
    • m: a current struct js *. In JS, pass null
    • p: any C pointer
    • v: valid only for the return value, means void

The imported C function must satisfy the following requirements:

  • A function must have maximum 6 parameters
  • C double parameters could be only 1st or 2nd. For example, function void foo(double x, double y, struct bar *) could be imported, but void foo(struct bar *, double x, double y) could not
  • C++ functions must be declared as extern "C"
  • Functions with float params cannot be imported. Write wrappers with double

Here are some example of the import specifications:

  • int sum(int) -> js_import(js, (uintptr_t) sum, "ii")
  • double sub(double a, double b) -> js_import(js, (uintptr_t) sub, "ddd")
  • int rand(void) -> js_import(js, (uintptr_t) rand, "i")
  • unsigned long strlen(char *s) -> js_import(js, (uintptr_t) strlen, "is")
  • char *js_str(struct js *, js_val_t) -> js_import(js, (uintptr_t) js_str, "smj")

In some cases, C APIs use callback functions. For example, a timer C API could specify a time interval, a C function to call, and a function parameter. It is possible to marshal JS function as a C callback - in other words, it is possible to pass JS functions as C callbacks.

A C callback function should take between 1 and 6 arguments. One of these arguments must be a void * pointer, that is passed to the C callback by the imported function. We call this void * parameter a "userdata" parameter.

The C callback specification is enclosed into the square brackets [...]. In addition to the signature letters above, a new letter u is available that specifies userdata parameter. In JS, pass null for u param. Here is a complete example:

#include <stdio.h>
#include "elk.h"

// C function that invokes a callback and returns the result of invocation
int f(int (*fn)(int a, int b, void *userdata), void *userdata) {
  return fn(1, 2, userdata);

int main(void) {
  char mem[500];
  struct js *js = js_create(mem, sizeof(mem));
  js_set(js, js_glob(js), "f", js_import(js, f, "i[iiiu]u"));
  jsval_t v = js_eval(js, "f(function(a,b,c){return a + b;}, 0);", ~0);
  printf("result: %s\n", js_str(js, v));  // result: 3
  return 0;

js_set(), js_glob(), js_mkobj()

jsval_t js_glob(struct js *);   // Return global object
jsval_t js_mkobj(struct js *);  // Create a new object
void js_set(struct js *, jsval_t obj, const char *key, jsval_t val);  // Assign property to an object

These are helper functions for assigning properties to objects. The anticipated use case is to give names to imported C functions.

Importing a C function sum into the global namespace:

  jsval_t global_namespace = js_glob(js);
  jsval_t imported_function = js_import(js, (uintptr_t) sum, "iii");
  js_set(js, global_namespace, "f", imported_function);

Use js_mkobj() to create a dedicated object to hold groups of functions and keep a global namespace tidy. For example, all GPIO related functions can go into the gpio object:

  jsval_t gpio = js_mkobj(js);              // Equivalent to:
  js_set(js, js_glob(js), "gpio", gpio);    // let gpio = {};

  js_set(js, gpio, "mode",  js_import(js, (uintptr_t) func1, "iii");  // Create gpio.mode(pin, mode)
  js_set(js, gpio, "read",  js_import(js, (uintptr_t) func2, "ii");   // Create
  js_set(js, gpio, "write", js_import(js, (uintptr_t) func3, "iii");  // Create gpio.write(pin, value)


int js_usage(struct js *);

Return memory usage percentage - a number between 0 and 100.

Download Details:
Author: cesanta
Download Link: Download The Source Code
Official Website: 
License: GPLv2



sophia tondon

sophia tondon


Top Laravel Development Company India | Laravel Development Services

Laravel is a popular framework for website development, acquiring 25.85% of the PHP framework market share. As a most admired framework among PHP frameworks, it is being utilized for e-commerce, enterprise, social media, and various different types of websites.

There are more than 1 million websites worldwide available over the web that are created using Laravel. Laravel framework is the first preference of PHP developers as it allows them to develop highly scalable, flexible, and faster web applications.

Surely, you, too, would want to deliver a splendid and unhindered user experience to your target audience over the web. Laravel framework can help you achieve this pursuit at ease; all you need to do is hire Laravel developers from reliable & coveted hosts. But! There is no shortage of Laravel development companies that promise to deliver an excellent solution, but only some are able to deliver top-notch quality.

Therefore, I have decided to enlist top Laravel development companies to help you find a reliable and expert host for web development. So, stay hooked with me till the end of this article and explore the best Laravel developers in 2021.

While creating this list, I have kept the following pointers in reflection:

Years of excellence (average 8 years)
Rewards & Recognition
Client rating & feedback
Hourly/Monthly Price
Number of happy clients
Number of successfully launched projects
Minimum man-years experience
So, let’s not waste a minute and glance at top Laravel development companies to hire for creating excellent web solutions.

Read More -

#hire a laravel developer #hire laravel developer #hire laravel developers #laravel developer for hire #laravel developers #laravel developers for hire