C ABI
Use liboliphaunt from C, C++, or a custom language binding.
Use liboliphaunt when you need a C boundary for native PostgreSQL. Application developers can usually start faster with a language SDK.
The ABI returns PostgreSQL protocol bytes and owns native response buffers. Your binding supplies typed decoding, scheduling, and application-level lifecycle.
Install and prepare storage
Download the native library, oliphaunt.h, and runtime resources for your platform from the native runtime release. Compile against the matching header and link the matching library. Preserve the release's runtime-resource layout.
oliphaunt_init opens the pgdata child of an already-prepared managed root. It does not initialize an empty directory. Prepare the root through a native SDK, close its owner, and then use the root from your C program. See Prepare a managed root.
Open and query
Save this as example.c. Its argument is the pgdata path inside your prepared root. runtime_dir and module_dir use release-layout discovery unless you set explicit paths.
#include <oliphaunt.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s /path/to/root/pgdata\n", argv[0]);
return 2;
}
OliphauntHandle *handle = NULL;
OliphauntErrorCapture error = {0};
OliphauntConfig config = {
.abi_version = OLIPHAUNT_ABI_VERSION,
.pgdata = argv[1],
.username = "postgres",
.database = "postgres",
};
if (oliphaunt_init_with_error(&config, &handle, &error) != 0) {
fprintf(stderr, "%s\n", error.message);
return 1;
}
OliphauntResponse response = {0};
const char *sql = "SELECT 42::int4 AS answer";
int32_t status = oliphaunt_exec_simple_query_with_error(
handle, sql, strlen(sql), &response, &error);
if (status != 0) fprintf(stderr, "%s\n", error.message);
else printf("Received %zu PostgreSQL protocol bytes\n", response.len);
oliphaunt_free_response(&response);
int32_t closed = oliphaunt_close(handle);
return status != 0 || closed != 0;
}The response is binary protocol data, not a string or a decoded row. Parse backend messages to read the result and detect PostgreSQL ErrorResponse messages. A successful transport call is not a substitute for inspecting the SQL result.
Next steps
Read Build a binding for scheduling, buffer ownership, and lifecycle. Use the API reference for configuration and function groups.