varlink is a neat little standard for doing debuggable IPC. It takes some of the nice properties of DBUS, like the introspection capabilities, and combines them with simple standard tools/technologies in the form of unix sockets and JSON.

For C, there is a library by emersion called vali, which does pretty much all you need to get going: https://emersion.fr/blog/2025/announcing-vali/

When you have written your service, here is how to interact with it just using standard utils, socat and jq:

cat <<-EOF | jq --raw-output0 | socat STDIO UNIX-CONNECT:"$SOCKET" | jq
    {
        "method": "org.varlink.service.GetInfo",
    }
EOF

This is equivalent to using the varlink cli tool and running: varlink info $SOCKET

cat <<-EOF | jq --raw-output0 | socat STDIO UNIX-CONNECT:"$SOCKET" | jq
    {
        "method": "org.varlink.service.GetInterfaceDescription",
        "parameters": {
            "interface": "com.example.Foobar"
        }
    }
EOF

This will return the service interface (if the service listening at the socket actually implements it.

Note the use of jq --raw-output0. It is possible to omit the jq invocations, the input JSON data should be followed by a NUL byte.