Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fail to call c++ static lib. #39455

Closed
sbilly opened this issue Jun 8, 2020 · 3 comments
Closed

Fail to call c++ static lib. #39455

sbilly opened this issue Jun 8, 2020 · 3 comments

Comments

@sbilly
Copy link

@sbilly sbilly commented Jun 8, 2020

What version of Go are you using (go version)?

$ go version
go version go1.14.3 darwin/amd64

Does this issue reproduce with the latest release?

Put main.cpp, main.hpp, main.go, Makefile in the same folder and run make.

main.cpp

int main(int argc,char **argv)
{
}

main.hpp

#ifndef AC_MAIN_GO_H
#define AC_MAIN_GO_H

int main(int argc,char **argv);

#endif // AC_MAIN_GO_H

main.go

package main

import (
	"fmt"
)

/*
#cgo LDFLAGS: -L. -lmain -lstdc++
#include "main.hpp"
#include <stdlib.h>
*/
import "C"

func main() {
	argv := C.CString("")

	fmt.Println(`before`)
	fmt.Println(C.main(C.int(0), &argv))
	fmt.Println(`after`)
	return
}

Makefile

CXX=c++
AR=ar
GO=go

default: main

all: main

main:
        $(CXX) -c main.cpp -o main.o
        $(AR) rcs libmain.a main.o
        $(GO) run main.go
$ make
c++ -c main.cpp -o main.o
ar rcs libmain.a main.o
go run main.go
before
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x5f0 pc=0x403f768]

runtime stack:
runtime/debug.setGCPercent(0x64, 0x64)
        /usr/local/Cellar/go/1.14.3/libexec/src/runtime/mgc.go:237 +0x69

goroutine 1 [syscall]:
runtime.cgocall(0x409fef0, 0xc000057ed0, 0xc000010028)
        /usr/local/Cellar/go/1.14.3/libexec/src/runtime/cgocall.go:133 +0x5b fp=0xc000057ea0 sp=0xc000057e68 pc=0x40051cb
main._Cfunc_main(0x0, 0xc000010028, 0x0)
        _cgo_gotypes.go:62 +0x4d fp=0xc000057ed0 sp=0xc000057ea0 pc=0x409fb8d
main.main.func1(0xc000010028, 0xc000010018)
        /Users/xxx/tmp/main.go:18 +0x6f fp=0xc000057f00 sp=0xc000057ed0 pc=0x409fe8f
main.main()
        /Users/xxx/tmp/main.go:18 +0xc7 fp=0xc000057f88 sp=0xc000057f00 pc=0x409fd37
runtime.main()
        /usr/local/Cellar/go/1.14.3/libexec/src/runtime/proc.go:203 +0x212 fp=0xc000057fe0 sp=0xc000057f88 pc=0x40338e2
runtime.goexit()
        /usr/local/Cellar/go/1.14.3/libexec/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000057fe8 sp=0xc000057fe0 pc=0x405de51
exit status 2
make: *** [main] Error 1

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN="/Users/xxx/.go/bin"
GOCACHE="/Users/xxx/Library/Caches/go-build"
GOENV="/Users/xxx/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/xxx/.go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn"
GOROOT="/usr/local/Cellar/go/1.14.3/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14.3/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/q3/27vpk30j2vj6zfdbs_9pvpzw0000gn/T/go-build237302644=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

As mentioned before

What did you expect to see?

It should return without error.

What did you see instead?

As mentioned before

@jeremyfaller
Copy link
Contributor

@jeremyfaller jeremyfaller commented Jun 8, 2020

I don't think cgo can handle C++ name mangling, and you need to export your C++ functions with an extern "C".

extern "C" void foo(int argc, char**argv) {
}

Note I also changed the name from main to foo. I have no idea what the go runtime/linker would try to call with your code, but could imagine it having real hard times resolving the symbol. I'll mark this as Closed, as I don't think there's an error here.

@jeremyfaller
Copy link
Contributor

@jeremyfaller jeremyfaller commented Jun 8, 2020

Thinking about it further, I'm going to reopen this. I think it might be valuable to fail earlier for the user. Your reasonable assumptions about what should happen should have failed in a more friendly manner.

@jeremyfaller jeremyfaller reopened this Jun 8, 2020
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jun 8, 2020

This actually isn't due to C++ symbol name mangling. C++ doesn't mangle the name main.

The problem is that the Go runtime also provides a symbol main, which is used to start the program when using external linking, as happens when using cgo.

So the upshot is that you can't use a symbol named main in your library. Which is true of C or C++ libraries in general anyhow.

I'm going to close this issue again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.