Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5963143
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T19:12:19+00:00 2026-05-22T19:12:19+00:00

I am trying to create a static object written in Go to interface with

  • 0

I am trying to create a static object written in Go to interface with a C program (say, a kernel module or something).

I have found documentation on calling C functions from Go, but I haven’t found much on how to go the other way. What I’ve found is that it’s possible, but complicated.

Here is what I found:

Blog post about callbacks between C and Go

Cgo documentation

Golang mailing list post

Does anyone have experience with this? In short, I’m trying to create a PAM module written entirely in Go.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T19:12:20+00:00Added an answer on May 22, 2026 at 7:12 pm

    You can call the Go code from C. It is a confusing proposition, though.

    The process is outlined in the blog post you linked to. But I can see how that isn’t very helpful. Here is a short snippet without any unnecessary bits. It should make things a little clearer.

    package foo
    
    // extern int goCallbackHandler(int, int);
    //
    // static int doAdd(int a, int b) {
    //     return goCallbackHandler(a, b);
    // }
    import "C"
    
    //export goCallbackHandler
    func goCallbackHandler(a, b C.int) C.int {
        return a + b
    }
    
    // This is the public function, callable from outside this package.
    // It forwards the parameters to C.doAdd(), which in turn forwards
    // them back to goCallbackHandler(). This one performs the addition
    // and yields the result.
    func MyAdd(a, b int) int {
       return int( C.doAdd( C.int(a), C.int(b)) )
    }
    

    The order in which everything is called is as follows:

    foo.MyAdd(a, b) ->
      C.doAdd(a, b) ->
        C.goCallbackHandler(a, b) ->
          foo.goCallbackHandler(a, b)
    

    The key to remember here is that a callback function must be marked with the //export comment on the Go side and as extern on the C side. This means that any callback you wish to use, must be defined inside your package.

    In order to allow a user of your package to supply a custom callback function, we use the exact same approach as above, but we supply the user’s custom handler (which is just a regular Go function) as a parameter that is passed onto the C side as void*. It is then received by the callbackhandler in our package and called.

    Let’s use a more advanced example I am currently working with. In this case, we have a C function that performs a pretty heavy task: It reads a list of files from a USB device. This can take a while, so we want our app to be notified of its progress. We can do this by passing in a function pointer that we defined in our program. It simply displays some progress info to the user whenever it gets called. Since it has a well known signature, we can assign it its own type:

    type ProgressHandler func(current, total uint64, userdata interface{}) int
    

    This handler takes some progress info (current number of files received and total number of files) along with an interface{} value which can hold anything the user needs it to hold.

    Now we need to write the C and Go plumbing to allow us to use this handler. Luckily the C function I wish to call from the library allows us to pass in a userdata struct of type void*. This means it can hold whatever we want it to hold, no questions asked and we will get it back into the Go world as-is. To make all this work, we do not call the library function from Go directly, but we create a C wrapper for it which we will name goGetFiles(). It is this wrapper that actually supplies our Go callback to the C library, along with a userdata object.

    package foo
    
    // #include <somelib.h>
    // extern int goProgressCB(uint64_t current, uint64_t total, void* userdata);
    // 
    // static int goGetFiles(some_t* handle, void* userdata) {
    //    return somelib_get_files(handle, goProgressCB, userdata);
    // }
    import "C"
    import "unsafe"
    

    Note that the goGetFiles() function does not take any function pointers for callbacks as parameters. Instead, the callback that our user has supplied is packed in a custom struct that holds both that handler and the user’s own userdata value. We pass this into goGetFiles() as the userdata parameter.

    // This defines the signature of our user's progress handler,
    type ProgressHandler func(current, total uint64, userdata interface{}) int 
    
    // This is an internal type which will pack the users callback function and userdata.
    // It is an instance of this type that we will actually be sending to the C code.
    type progressRequest struct {
       f ProgressHandler  // The user's function pointer
       d interface{}      // The user's userdata.
    }
    
    //export goProgressCB
    func goProgressCB(current, total C.uint64_t, userdata unsafe.Pointer) C.int {
        // This is the function called from the C world by our expensive 
        // C.somelib_get_files() function. The userdata value contains an instance
        // of *progressRequest, We unpack it and use it's values to call the
        // actual function that our user supplied.
        req := (*progressRequest)(userdata)
        
        // Call req.f with our parameters and the user's own userdata value.
        return C.int( req.f( uint64(current), uint64(total), req.d ) )
    }
    
    // This is our public function, which is called by the user and
    // takes a handle to something our C lib needs, a function pointer
    // and optionally some user defined data structure. Whatever it may be.
    func GetFiles(h *Handle, pf ProgressFunc, userdata interface{}) int {
       // Instead of calling the external C library directly, we call our C wrapper.
       // We pass it the handle and an instance of progressRequest.
    
       req := unsafe.Pointer(&progressequest{ pf, userdata })
       return int(C.goGetFiles( (*C.some_t)(h), req ))
    }
    

    That’s it for our C bindings. The user’s code is now very straight forward:

    package main
    
    import (
        "foo"
        "fmt"
    )
    
    func main() {
        handle := SomeInitStuff()
        
        // We call GetFiles. Pass it our progress handler and some
        // arbitrary userdata (could just as well be nil).
        ret := foo.GetFiles( handle, myProgress, "Callbacks rock!" )
    
        ....
    }
    
    // This is our progress handler. Do something useful like display.
    // progress percentage.
    func myProgress(current, total uint64, userdata interface{}) int {
        fc := float64(current)
        ft := float64(total) * 0.01
    
        // print how far along we are.
        // eg: 500 / 1000 (50.00%)
        // For good measure, prefix it with our userdata value, which
        // we supplied as "Callbacks rock!".
        fmt.Printf("%s: %d / %d (%3.2f%%)\n", userdata.(string), current, total, fc / ft)
        return 0
    }
    

    This all looks a lot more complicated than it is. The call order has not changed as opposed to our previous example, but we get two extra calls at the end of the chain:

    The order is as follows:

    foo.GetFiles(....) ->
      C.goGetFiles(...) ->
        C.somelib_get_files(..) ->
          C.goProgressCB(...) ->
            foo.goProgressCB(...) ->
               main.myProgress(...)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to create a generic class which will have some static functions based
Trying to create a user account in a test. But getting a Object reference
I am trying to call a method I have written in C# from VBScript.
I'm trying to create a self referencing object using linqTOsql mapping. So far, I
I use a static function to create a PDO object. It accepts 2 params:
I’m trying to create a count down timer. I user a Timer object that
I'm trying to use a static library created by me in Visual C++ 2005
I am trying create a WCF service that leverages the WPF MediaPlayer on the
Trying to create a QtRuby application, I get the following error: /usr/lib64/ruby/site_ruby/1.8/Qt/qtruby4.rb:2144: [BUG] Segmentation
Trying to create my first iPhone app that would play back audio. When I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.