C library and ABI

Artifact types, plainly

Extension What it is
.a A static archive of object files. The linker copies the parts your program actually calls into your executable at link time; the result doesn't need libpolycall present at run time.
.so A Unix (Linux/BSD) shared library, loaded at run time.
.dll A Windows shared library, loaded at run time.
.exe A Windows executable. Plain (no extension) executables on Linux/macOS are the same concept.

On Windows, linking against a .dll from a separate compilation normally goes through a small import library (a .dll.a for MinGW, or a .lib for MSVC) generated alongside the DLL — it's not the DLL itself, just linker metadata pointing at it. See the note below: this repository's default build does not currently generate one.

What make all / build-windows.ps1 actually produces

lib/libpolycall.a      static archive          (both platforms)
lib/libpolycall.so     shared library          (Linux)
lib/libpolycall.dll    shared library          (Windows)
bin/polycall(.exe)     CLI, statically linked against libpolycall.a
bin/math-provider(.exe) C provider example, statically linked

Shared linking isn't fully wired up yet

Both platforms build a shared library, but the CLI itself links against the static archive (gcc ... lib/libpolycall.a -o bin/polycall), and the Windows build does not currently emit an import library for libpolycall.dll (no -Wl,--out-implib=... in the link step). If you want to dynamically link an external consumer against the DLL today, you'll need to generate that import library yourself (or link directly against the .dll the way MinGW allows). Versioned shared-library naming (libpolycall.so.1.0.0 with an libpolycall.so.1 SONAME symlink), a generated polycall.pc for pkg-config, and an installed CMake package (find_package / Polycall::polycall) are all described as targets in LPV1-03 but are not implemented — the plain filenames above are what exists.

Public headers

#include <polycall/polycall.h>
#include <polycall/polycall_provider.h>   /* only if writing a provider */

Both live under include/polycall/, use only the polycall_/POLYCALL_ prefix, and pull in no private project header, no pthreads, no Winsock — consistent with ABI-003.

Representative declarations from polycall.h (see the header itself for the authoritative, complete list — this is not a frozen ABI manifest, which ABI-005 still calls a target, not a shipped artifact):

const char* polycall_version_string(void);
uint32_t    polycall_abi_version(void);

polycall_status_t polycall_config_parse_file(const char* path, size_t path_len,
    polycall_config_t* out_config, polycall_result_t* out_error);

polycall_status_t polycall_runtime_create(polycall_config_t config, polycall_runtime_t* out_runtime);
polycall_status_t polycall_runtime_start(polycall_runtime_t runtime);
polycall_status_t polycall_runtime_stop(polycall_runtime_t runtime, uint32_t drain_timeout_ms);

polycall_status_t polycall_call_submit(/* service, method, args, timeout, callback, ... */);
polycall_status_t polycall_result_status(polycall_result_t result);
const char*        polycall_result_message(polycall_result_t result, size_t* out_byte_length);

Stateful objects (polycall_config_t, polycall_runtime_t, polycall_result_t, polycall_value_t, ...) are opaque handles — no caller-visible struct layout to allocate or poke at directly.

The provider API

polycall_provider.h is the surface examples/quickstart-math/math_provider.c uses in full, and nothing else:

polycall_provider_t polycall_provider_connect(const char* config_path, char** out_error);
bool polycall_provider_register_method(provider, service, provider_id, method_name,
    param_types, param_count, result_type, handler, user_data, &out_error);
polycall_status_t polycall_provider_serve(provider, &out_error);
void polycall_provider_close(provider);

Its documented scope, from the header's own comment: one call served at a time per connection — it is not a concurrent-provider framework.

Linking a consumer

From a repository build, using the staged include/ and lib/:

cc -std=c11 -Iinclude -c consumer.c -o consumer.o
cc consumer.o -Llib -lpolycall -o consumer

-Llib tells the linker to search a directory named lib relative to the compiler's current working directory — it is a linker search path, not a run-time loader search path, and it doesn't do anything with bin/polycall itself. This resolves to the static archive by default (there is currently no separate shared-library consumer example or documented deployment layout for libpolycall.so/.dll — see the warning above). Object files must precede -lpolycall on the link line for archive resolution to find the symbols they need.

Do not copy an arbitrary downloaded DLL into a system directory to satisfy a missing dependency — if a loader can't find libpolycall.dll/.so, that's a deployment/path problem to diagnose (place it beside the consumer, or set an explicit loader path), not something to paper over with an unrelated file.