{"id":17919653,"url":"https://github.com/enobufs/go-calls-c-pointer","last_synced_at":"2025-03-24T00:31:55.591Z","repository":{"id":68689755,"uuid":"164202593","full_name":"enobufs/go-calls-c-pointer","owner":"enobufs","description":"A cgo example: how to call C function pointer from Go.","archived":false,"fork":false,"pushed_at":"2019-01-05T19:18:55.000Z","size":7,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T17:37:59.627Z","etag":null,"topics":["callback","cgo","function-pointer","go","golang","shared-library"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/enobufs.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-05T09:57:35.000Z","updated_at":"2024-01-07T09:11:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"2e918ff6-f01c-4e19-9293-b0a295695ab0","html_url":"https://github.com/enobufs/go-calls-c-pointer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enobufs%2Fgo-calls-c-pointer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enobufs%2Fgo-calls-c-pointer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enobufs%2Fgo-calls-c-pointer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enobufs%2Fgo-calls-c-pointer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enobufs","download_url":"https://codeload.github.com/enobufs/go-calls-c-pointer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221925666,"owners_count":16902742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["callback","cgo","function-pointer","go","golang","shared-library"],"created_at":"2024-10-28T20:18:30.410Z","updated_at":"2024-10-28T20:18:30.842Z","avatar_url":"https://github.com/enobufs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to make a callback into C from Go\n\n## Example: Count() method with a callback from Go\n### C Code\nHere's the `main.c`:\n```c\n#include \"libcounter.h\"\n#include \u003cstdio.h\u003e\n\nvoid onCount(int n) {\n    printf(\"Count: %d\\n\", n);\n}\n\nint main(void) {\n    int rc = Count(3, onCount); // implemented in Go\n    printf(\"Done!\\n\");\n    return rc;\n}\n```\n\nThe `Count()` method is implemented in Go, which is compiled as a shared library. The\nmethod takes a number and a callback function. It calls the callback function, specified\nnumber of times, with interval of 1-second, then exits.\n\n### Go Code\nHere's the implemention of `Count()` method in Go:\n\ncounter_api.go:\n```go\npackage main\n\n// typedef void (*count_cb)(int);\n// void makeCallback(int sum, count_cb cb);\nimport \"C\"\n\n//export Count\nfunc Count(n C.int, cb C.count_cb) int {\n\tgoCb := func(n int) {\n\t\tC.makeCallback(C.int(n), cb)\n\t}\n\treturn count(int(n), goCb)\n}\n```\n\ncounter.go:\n```go\npackage main\n\n// typedef void (*count_cb)(int);\n// extern void bridge(int sum, count_cb cb) {\n//     cb(sum);\n// }\nimport \"C\"\nimport (\n\t\"time\"\n)\n\ntype countCb func(n int)\n\nfunc count(n int, goCb countCb) int {\n\tfor i := 0; i \u003c n; i++ {\n\t\ttime.Sleep(time.Second * 1)\n\t\tgoCb(i + 1)\n\t}\n\n\treturn 0\n}\n\nfunc main() {}\n```\n## How to Build\nFirst build a shared library from Go code.\n```sh\ngo build -v -buildmode=c-shared -o libcounter.so *.go\n```\n\nThen build a C executable using the library.\n```sh\ngcc -o main main.c libcounter.so\n```\n\n\u003e Makefile is provided. For a quick build, type `make`.\n\nTo run:\n```\n$ ./main\nCount: 1\nCount: 2\nCount: 3\nDone!\n```\n\nAlso try:\n```\n$ go run counter.go\n```\nIt demonstrate that by putting C-typed (binding) code as a separate file\n(seen as counter_api.go), the rest of `pure` Go code become testable and\nrunnable within Go land.\n\n## Comments / Tips\n* No blank-line between C-code comment lines and `import \"C\"`\n* Go code can call C-function in the comment lines. But;\n* Go code can NOT directly call function *pointer*.\n* Go method meant to be called by C must have `//export Xxx` right above the function.\n* The `*.go` file that contains `//export Xxx` cannot have definition in the comment line, declaration only. (see counter.go)\n* For that reason, use a sperate go file to place the definition. (see counter.go)\n* No space between `//` and `expose`. (`// export Xxx` is tempting, but wound't work)\n* For more details, see [The Go Programming Language, Command cgo](https://golang.org/cmd/cgo/).\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenobufs%2Fgo-calls-c-pointer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenobufs%2Fgo-calls-c-pointer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenobufs%2Fgo-calls-c-pointer/lists"}