dingrui
dingrui

Reputation: 507

multiple definition when using cgo

package main

/*
int add(int a, int b) {
    return a + b;
}
*/
import "C"
import "fmt"

func main() {}

func Test1() {
    fmt.Println(C.add(1, 3))
}

//export Test2
func Test2() {

}

Compile the programe:

dingrui@dingrui-PC:~/Projects/gotest/array$ go build -o libtest.so -buildmode=c-shared main.go 
# command-line-arguments
/tmp/go-build043762604/b001/_x002.o: In function `add':
./main.go:5: multiple definition of `add'
/tmp/go-build043762604/b001/_x001.o:/tmp/go-build/main.go:5: first defined here
collect2: error: ld returned 1 exit status

If I delete the "//export Test2" line, it compile successfully.

Upvotes: 3

Views: 5001

Answers (2)

ypsu
ypsu

Reputation: 1387

Here's an ugly workaround if you don't mind duplicate code hanging around:

package main

/*
__attribute__((weak))
int add(int a, int b) {
    return a + b;
}
*/
import "C"
import "fmt"

func main() {}

func Test1() {
    fmt.Println(C.add(1, 3))
}

//export Test2
func Test2() {

}

IIUC __attribute__((weak)) tells the linker to ignore duplicated definitions.

Upvotes: 2

Mohammad Fahim Abrar
Mohammad Fahim Abrar

Reputation: 539

This behavior is documented here

Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations. If a file contains both definitions and declarations, then the two output files will produce duplicate symbols and the linker will fail. To avoid this, definitions must be placed in preambles in other files, or in C source files.

Upvotes: 7

Related Questions