[Resolved] Can't a cgo program be compiled into a c-archive?

package main

/*
int Add(int i) {
        return i + 1;
}
*/
import "C"
import "fmt"

func main() {
}

//export Foo
func Foo() {
        fmt.Printf("Foo!\n")
        C.Add(1)
}

$ go build -buildmode=c-archive mde.go
# command-line-arguments
/tmp/go-build123475493/command-line-arguments/_obj/mde.cgo2.o: In function `Add':
./mde.go:5: multiple definition of `Add'
/tmp/go-build123475493/command-line-arguments/_obj/_cgo_export.o:../mde.go:5: first defined here
collect2: error: ld returned 1 exit status

I’m trying to implement a way to register a c-function as a callback:

package main

// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
//		return f();
// }
//
// int fortytwo()
// {
//	    return 42;
// }
import "C"
import "fmt"
import "unsafe"

var handler C.intFunc

// export SetCallback
func SetCallback(f unsafe.Pointer) {
    handler = c.intFunc(f)
}

// export Call 
func Call() {
    // here do something in Go, like starting a http server, run the registered callback in a request handler and send back the result in response
    c.bridge_int_func(fh);
}

func main() {
}

compile the code above into a c-archive file, then in the c-program I will call SetCallback to register callback and then Call to start a server.

But as I say, the go file can’t be compiled with -buildmode=c-archive.

Any workaround about this? My main program must be written in C, don’t suggest me to change this please, Thanks.

That is, I want to link my C program with a go c-archive(C calls Go-Function), then in the c-archive go calls a C-Function registered dynamically(Go calls back to C). Hope I’m clear enough, thanks.

I got your first example working. The problem seems to have something to do with Add() being defined and Foo() being exported from the same Go file. Do one or the other and building it works.

The way I got it to work in this case was to use three files. Put them in the same directory and run go build or go build -buildmode c-archive to get your desired result. I expect the same method will work for your second example.

mde.go

package main

/*
#include "mde.h"
*/
import "C"
import "fmt"

func main() {
}

//export Foo
func Foo() {
	fmt.Printf("Foo!\n")
	C.Add(1)
}

mde.h

int Add(int i);

mde.c

int Add(int i) {
	return i + 1;
}

While I named all of these files mde.*, the names aren’t important as long as they have the right extensions and the .go file includes the .h file. An added benefit of splitting into three files is proper language support in your editor.

1 Like

That works fine for me, Many thanks.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.