npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

prolog-polycall

v1.1.0

Published

SWI-Prolog foreign library for the Polycall binding ABI v1 (libpolycall >= 1.1.0): config validation, RPC calls and peer nodes

Readme

prolog-polycall

SWI-Prolog binding for the Polycall core's binding ABI v1 (polycall.h, libpolycall >= 1.1.0): configuration validation, polycall_rpc calls and peer-to-peer nodes. npm source distribution prolog-polycall (not published yet).

src/prolog_polycall.c is a SWI-Prolog foreign library that includes the real <polycall.h> and links the core through pkg-config; src/prolog_polycall.pl is the Prolog module. Configuration parsing, the wire protocols and the peer transport stay in libpolycall.

Build

Requirements: SWI-Prolog >= 9 (swipl, headers), a C11 compiler, make, pkg-config, and the Polycall core >= 1.1.0 installed with its polycall.pc.

export PKG_CONFIG_PATH=/opt/polycall/lib/pkgconfig   # if the core is not in a system prefix
make                                                 # -> lib/prolog_polycall.so
swipl -p foreign=lib examples/basic.pl prolog-polycallrc

On Linux the foreign library is linked with -z now and a RUNPATH to the core's libdir: a missing core or an old 1.0 core without the ABI v1 symbols makes use_foreign_library/1 fail with a clear dynamic-loader error. A core whose polycall_ffi_abi_version() is not 1 is reported when the module loads and every API predicate then throws polycall_error(-15, 'POLYCALL_E_UNSUPPORTED', ...) — it is never used.

On Windows (MSYS2 UCRT64 / MinGW-w64 GCC with GNU make), the Makefile's Windows_NT branch builds lib/prolog_polycall.dll, linking libswipl from the SWI-Prolog installation (PLBASE/bin) and the core's import library through pkg-config, e.g. the UCRT64 core (libpolycall.dll, lib/libpolycall.dll.a, lib/pkgconfig/polycall.pc):

export PKG_CONFIG_PATH=/c/polycall/lib/pkgconfig    # the core's prefix
make SWIPL="/c/Program Files/swipl/bin/swipl.exe"
PATH="/c/polycall/bin:$PATH" swipl -p foreign=lib examples/basic.pl prolog-polycallrc

A DLL resolves its imports when it is loaded, so a missing core or a 1.0 core without the ABI v1 symbols makes use_foreign_library/1 fail there too. QA status: built and tested on Linux x86_64 (SWI-Prolog 10.1.16 and 9.0.4); the Windows and macOS (Darwin) branches are implemented but have not been run in QA yet (no SWI-Prolog on the Windows QA host, no macOS host).

API (module prolog_polycall)

:- use_module(library(prolog_polycall)).   % or use_module('src/prolog_polycall')

?- polycall_abi_version(1), polycall_version(V).
?- run_config('prolog-polycallrc', Status).       % polycall_ffi_run_config(Path, 1); Status unchanged
?- run_config('prolog-polycallrc', false, S).     % run=0: unknown keys are warnings
?- run_config_or_throw('prolog-polycallrc').
?- polycall_describe('prolog-polycallrc', JSON).

% one polycall_rpc round trip to `polycall start` / `polycall daemon start`
?- polycall_call('127.0.0.1:8084', inventory, get, '{"item_id":"widget-a"}', 2000, Out).

?- peer_open(alpha, "127.0.0.1:0", '', H),       % '' bind = send-only, '' token = none
   peer_register(H, beta, '127.0.0.1:9002'),
   peer_send(H, beta, utf8("hello"), 'msg-1', 5000),
   peer_recv(H, 5000, message(Sender, MessageId, Payload)),
   peer_list(H, Pairs), peer_health(H, JSON), peer_ping(H, beta, 2000),
   peer_unregister(H, beta), peer_cancel(H), peer_close(H).

Payloads are octets: a string/atom/code list of chars 0..255 (binary-safe, NUL allowed), or utf8(Text). Received payloads are strings of octets. Timeouts are milliseconds or infinite. Failures throw

error(polycall_error(Status, Name, Detail), context(Pred/Arity, _))

with the POLYCALL_E_* status, its polycall_strerror name and the polycall_last_error detail of this thread. polycall_call/6 adds the remote error object (polycall_error(Status, Name, Detail, Output)), and a peer_recv/4 with a too-small capacity throws polycall_error(-10, 'POLYCALL_E_TOO_LARGE', Detail, needed(Bytes)) and leaves the message queued. A peer_recv blocked in one thread is woken by peer_cancel/1 or peer_close/1 from another; other Prolog threads keep running while one is blocked in the core, but the blocked thread handles thread_signal/2 (e.g. an abort) only after the call returns.

Arguments are checked before they reach C, with standard Prolog errors: timeouts must be integers in 0..4294967295 or infinite (domain_error(polycall_timeout_ms, T), type_error(integer, T)), handles must fit int32 (domain_error(polycall_handle, H)), a peer_recv/4 capacity must be >= 0 (domain_error(polycall_capacity, C); capacities above the 1 MiB message limit are clamped, never allocated), and text arguments (paths, ids, endpoints, JSON, tokens) must not contain code 0, which would reach C silently truncated (domain_error(polycall_text, T)).

Changed in 1.1.0: errors were polycall_error(Status); they now carry the name and detail.

Tests

tests/run-real-core.sh builds the foreign library and runs the PlUnit suite (tests/prolog_polycall_tests.pl) against the real installed core: version/ABI, a missing core, an old core and an ABI 2 core in child swipl processes, run_config, polycall_call against a live polycall start runtime, two nodes both directions, payload matrix (empty, UTF-8, binary + NUL, 1 MiB, 1 MiB + 1), registry ownership, de-duplication, auth, dead peers, timeouts, small buffers, cancel and close waking blocked receivers (threads), handle lifecycle, 8 concurrent sender threads, argument bounds (timeouts, capacities, handles, NUL in text), a non-ASCII configuration path, and interop with a polycall peer serve C node. A missing swipl, make, pkg-config or core is reported as SKIP (exit 77), never as success; the run fails unless every test ran and passed.

sh tests/run-real-core.sh            # core in /opt/polycall, or POLYCALL_PREFIX / POLYCALL_LIBRARY
sh tests/run-memcheck.sh asan        # the foreign library under ASan + UBSan
sh tests/run-memcheck.sh valgrind    # the whole suite under valgrind memcheck

The ASan run preloads the sanitizer runtime into swipl with use_sigaltstack=0: SWI-Prolog installs its own alternate signal stack per thread, and ASan's default would try to unmap that buffer when the thread exits (an ASan CHECK failure that is not a defect in this code).

License

MIT, Nnamdi Michael Okpala ([email protected]), see LICENSE.