Search code examples
gocgo

Calling c function, order of "import fmt", "import C" is causing build error, why?


I have the following simple test go code : call_c.go

package main

/*
int getData(int *p, int n )
{
     int i; 
     for(i=0;i<n;i++) {
        p[i]=i;
    } 
    return n;
}
*/
import "C"
import "fmt"

func main() {
    var a [5]int32
    i := C.getData((*C.int)(&a[0]), 5)
    fmt.Println(i, a)
}

I use "go build call_c.go" to build the program and that builds fine.

But I found that if I simplely reverse the order of "import fmt", "import C" or add a newline between the C /* */ block code and the first import statement, the "go build call_c.go" command will return an error:

go build call_c.go
37: error: 'getData' undeclared (first use in this function)

Questions for expert gophers out there:

Why is the order of import important in go?

Why can't I add space between C block and the first import statement?

If I see this kind of error again, how best to debug it?


Solution

  • The order of import arn't generally important. But import "C" is very special when using cgo.

    From the docs:

    If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:

    // #include <stdio.h>
    // #include <errno.h>
    import "C"
    

    So, if you have a newline between your comment which contain the C code, and the import "C" , then the comment is just another comment, and isn't processed by cgo.

    Similarly if you reverse the order of import:

    /*
    int getData(int *p, int n )
    {
         int i; 
         for(i=0;i<n;i++) {
            p[i]=i;
        } 
        return n;
    }
    */
    import "fmt"
    import "C"
    

    The code in the comment is just another comment and isn't processed by cgo since it isn't immediately followed by an import "C". (or rather, import "C" isn't preceded by a comment)