{"id":19602638,"url":"https://github.com/wang-bin/capi","last_synced_at":"2026-03-09T10:01:22.241Z","repository":{"id":20982190,"uuid":"24271388","full_name":"wang-bin/capi","owner":"wang-bin","description":"Use C api as dynamically loaded calls in C++. Header only. Used by QtAV project(libass, libEGL API)","archived":false,"fork":false,"pushed_at":"2022-04-01T04:34:55.000Z","size":76,"stargazers_count":9,"open_issues_count":1,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-05T01:51:15.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wang-bin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-09-20T18:50:58.000Z","updated_at":"2023-11-03T15:06:34.000Z","dependencies_parsed_at":"2022-07-30T03:17:58.052Z","dependency_job_id":null,"html_url":"https://github.com/wang-bin/capi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wang-bin/capi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang-bin%2Fcapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang-bin%2Fcapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang-bin%2Fcapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang-bin%2Fcapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wang-bin","download_url":"https://codeload.github.com/wang-bin/capi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang-bin%2Fcapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30290895,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T09:25:12.415Z","updated_at":"2026-03-09T10:01:22.201Z","avatar_url":"https://github.com/wang-bin.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# capi\n\nThis header only tool helps you use C APIs in a shared library by dynamically loading instead of linking against it with minimal efforts.\n\nOnly depends on std C++\n\nHere is a simple zlib example, if you want use zlib functions, inherits class zlib::api.\n\n\u003edefine a class with zlib functions in zlib_api.h\n\n    #ifndef CAPI_LINK_ZLIB\n    namespace zlib { //need a unique namespace\n    namespace capi {\n    #else\n    extern \"C\" {\n    #endif\n    #include \"zlib.h\" //// we need some types define there. otherwise we can remove this\n    #ifndef CAPI_LINK_ZLIB\n    }\n    #endif\n    }\n\n    namespace zlib { //need a unique namespace\n    #ifndef CAPI_LINK_ZLIB\n    using namespace capi;\n    #endif\n    class api_dll; //must use this name\n    class api //must use this name\n    {\n        api_dll *dll;\n    public:\n        api();\n        virtual ~api();\n        virtual bool loaded() const;\n    #if !defined(CAPI_LINK_ZLIB) \u0026\u0026 !defined(ZLIB_CAPI_NS)\n        const char* zlibVersion();\n        const char* zError(int);\n    #endif\n    };\n    } //namespace zlib\n    #ifdef ZLIB_CAPI_NS\n    using namespace zlib::capi;\n    #else\n    using namespace zlib;\n    #endif\n\n`zlib_api.h` is the header you will use\n\n\u003ezlib_api.cpp (some code can be generated from  tools/mkapi)\n\n    #define DEBUG //log dll load and symbol resolve\n    //#define CAPI_IS_LAZY_RESOLVE 0 //define it will resolve all symbols in constructor\n    #include \"capi.h\"\n    #include \"zlib_api.h\" //include last because zlib.h was in namespace capi to avoid covering types later\n\n    namespace zlib {\n    static const char* zlib[] = {\n    #ifdef CAPI_TARGET_OS_WIN\n        \"zlib\",\n    #else\n        \"z\",\n    #endif\n        NULL\n    };\n    static const int versions[] = { 0, ::capi::NoVersion, 1, ::capi::EndVersion };\n    CAPI_BEGIN_DLL_VER(zlib, versions, ::capi::dso) // you can also use QLibrary or your custom library resolver instead of ::capi::dso\n    CAPI_DEFINE_ENTRY(const char*, zlibVersion, CAPI_ARG0())\n    CAPI_DEFINE_ENTRY(const char*, zError, CAPI_ARG1(int))\n    CAPI_END_DLL()\n    CAPI_DEFINE_DLL\n    CAPI_DEFINE(const char*, zlibVersion, CAPI_ARG0())\n    CAPI_DEFINE(const char*, zError, CAPI_ARG1(int))\n    } //namespace zlib\n\n\u003etest.cpp (dynamically loaded symbols, not link to zlib):\n\n    //#define ZLIB_CAPI_NS // namespace style\n    //#define CAPI_LINK_ZLIB // direct linkt to zlib. add -lz is required\n    #include \u003cstdio.h\u003e\n    #include \"zlib_api.h\"\n\n    class test_zlib_api\n    #ifndef ZLIB_CAPI_NS\n                : protected zlib::api // will unload library in dtor\n    #endif\n    {\n    public:\n        void test_version() {\n            printf(\"zlib version: %s\\n\", zlibVersion());\n        }\n        void test_zError(int e) {\n            printf(\"zlib error: %d =\u003e %s\\n\", e, zError(e));\n        }\n    };\n\n    int main(int, char **)\n    {\n        test_zlib_api tt;\n        printf(\"capi zlib test\\n\");\n        tt.test_version();\n        tt.test_version();\n        tt.test_zError(1);\n        return 0;\n    }\n\n### 3 Styles\n\nThe same code support 3 styles with only 1 line change in you code (test.cpp above)! You can switch class style and namespace without rebuild api implementation object(zlib_api.cpp).\n\n- **Class style(the default)**\n\n  All the functions you call are from class `zlib:api` and your class must be a subclass of it.\n\n- **Namespace style**\n\n  All the functions you call are from namesoace `zlib:capi`. Must add `#define ZLIB_CAPI_NS` before `#include \"zlib_api.h\"`.\n\n  It's easier to use than class style. It is not the default style because if the library is loaded and unloaded multiple times, symbol addresses from first load(wrong!) are used in current implementation.\n\n- **Direct link style**\n\n  The original functions are called. Must add `#define CAPI_LINK_ZLIB` before `#include \"zlib_api.h\"`, add `-DCAPI_LINK_ZLIB` to rebuild zlib_api.cpp add `-lz` flags to the compiler\n\n### Lazy Resolve\n\nThe symbol is resolved at the first call. You can add `#define CAPI_IS_LAZY_RESOLVE 0` in zlib_api.cpp before `#include \"capi.h\"` to resolve all symbols as soon as the library is loaded.\n\n### Auto Code Generation\n\nThere is a tool to help you generate header and source: https://github.com/wang-bin/mkapi\n\nThe tool is based on clang 3.4.\n\nAll you need to do is simply run the tool and use the generated files in your project, maybe with a few modifications.\n\nRun `make` to build the tool then run `./mkapi.sh -name zlib zlib.h -I` to generate zlib_api.h and zlib_api.cpp.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwang-bin%2Fcapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwang-bin%2Fcapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwang-bin%2Fcapi/lists"}