英文:
Not able to compile with cgo
问题
你正在使用的Go版本是什么(go version)?
$ go version
go version go1.20.2 linux/amd64
项目结构:
目录结构 --
example --> main.go
--> lib
lib.c
lib.h
main.go
package main
// #include "lib/lib.h"
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import (
"fmt"
"unsafe"
)
func main() {
cstrin := C.CString("welcome")
s1 := C.struct_s1{b: cstrin, a: 100}
C.f32_123(&s1)
cs := C.GoString(s1.b)
fmt.Println(cs)
fmt.Println(s1)
C.free(unsafe.Pointer(cstrin))
}
lib/lib.c
#include <stdlib.h>
#include <stdio.h>
void printc(char *str, int *t)
{
str = "Test";
printf("%d\n", *t);
*t = 30;
printf("%s\n", str);
}
void f32_123(struct s1 *s)
{
printf("%s\n", s->b);
s->a = 10;
s->b = "Hello123";
printf("%d\n", s->a);
printf("%s\n", s->b);
}
lib/lib.h
struct s1 {
int a;
char *b;
};
void printc(char *str, int *t);
void f32_123(struct s1 *s);
编译时出现错误
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-3024881602/000001.o: in function `_cgo_cf24297edd23_Cfunc_f32_123': /tmp/go-build/cgo-gcc-prolog:49: undefined reference to `f32_123'
collect2: error: ld returned 1 exit status
我期望代码能够成功编译,但不知何故却没有成功。如果我正确阅读了文档,那么我必须将lib.c
和lib.h
与main.go
文件放在同一个目录中。但我不确定是否可以实现这一点,或者我是否做错了什么。
- 如果我将所有文件放在同一个目录
example
中,则编译成功。 - 如果我将
lib.c
和lib.h
放在子目录中,则编译失败。 - 如果我从
main.go
中删除一个函数f32_123
,则编译也会成功,这非常奇怪,这就是我打开这个错误的原因,希望能更好地理解为什么当lib.h
和lib.c
在子目录中时,编译没有问题。
英文:
What version of Go are you using (go version)?
$ go version
go version go1.20.2 linux/amd64
Project structure:
Directory structure --
example --> main.go
-->lib
lib.c
lib.h
main.go
package main
// #include "lib/lib.h"
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import (
"fmt"
"unsafe"
)
func main() {
cstrin := C.CString("welcome")
s1 := C.struct_s1{b: cstrin, a: 100}
C.f32_123(&s1)
cs := C.GoString(s1.b)
fmt.Println(cs)
fmt.Println(s1)
C.free(unsafe.Pointer(cstrin))
}
lib/lib.c
#include <stdlib.h>
#include <stdio.h>
void printc(char *str, int *t)
{
str = "Test";
printf("%d\n", *t);
*t = 30;
printf("%s\n", str);
}
void f32_123(struct s1 *s)
{
printf("%s\n", s->b);
s->a = 10;
s->b = "Hello123";
printf("%d\n", s->a);
printf("%s\n", s->b);
}
lib/lib.h
struct s1 {
int a;
char *b;
};
void printc(char *str, int *t);
void f32_123(struct s1 *s);
Error while compiling
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-3024881602/000001.o: in function _cgo_cf24297edd23_Cfunc_f32_123': /tmp/go-build/cgo-gcc-prolog:49: undefined reference to f32_123'
collect2: error: ld returned 1 exit status
I am expecting the code to compile successfully, but somehow it is not. If I've read the documentation correctly, then I have to keep lib.c
and lib.h
in the same directory with the main.go
file. But I am not sure if this can be achieved or I am doing something wrong.
-
If I keep all the files into same directory example then compile is successful.
-
If I keep
lib.c
andlib.h
into subdir then compile fails -
If I remove one function
f32_123
from main.go then also compile is successful and that is pretty strange and that is the reason opening this bug to get more understanding why compile has not issue with printc function whenlib.h
andlib.c
is in subdir.
答案1
得分: 0
首先,@JimB在一段时间前给出了这个被接受的答案:https://stackoverflow.com/a/28881331/5739452,其中说在子目录中构建对象或库不是go build
可以直接做的事情。
鉴于此,假设您有以下结构:
lib/
lib/lib.c
lib/lib.h
main.go
这里有一些更简单的文件,以保持清晰:
/* lib/lib.h */
struct foo {
int x;
};
void show(struct foo *arg);
/* lib/lib.c */
#include <stdio.h>
#include "lib.h"
void show(struct foo *arg) {
printf("[%d]\n", arg->x);
}
所以,如果您有一个像这样的main.go
,您可以通过go build main.go
来构建所有内容:
package main
// #cgo CFLAGS: -I${SRCDIR}/lib
// #include "lib.c"
import "C"
func main() {
x := C.struct_foo{ x: 42 }
C.show(&x)
}
这可以工作,因为我们实际上#include
了库的"C"源代码(这隐式导入了lib/lib.h
文件)。
然而,对于更复杂的库,您可能需要将它们作为单独的、更常规的C工具链进行构建,预先进行构建步骤:
$ cd lib
$ cc -c lib.c
$ ar cr libx.a lib.o
$ cd ..
然后使用不同的Go文件:main2.go
:
package main
// #cgo CFLAGS: -I${SRCDIR}/lib
// #cgo LDFLAGS: -L${SRCDIR}/lib -lx
// #include "lib.h"
import "C"
func main() {
x := C.struct_foo{ x: 42 }
C.show(&x)
}
英文:
First, @JimB gave this accepted answer a while back: https://stackoverflow.com/a/28881331/5739452 which says that building an object or library in a sub directory isn't something go build
can just do.
Given that, let's say you have this structure:
lib/
lib/lib.c
lib/lib.h
main.go
Here are some simpler files to keep things clear:
/* lib/lib.h */
struct foo {
int x;
};
void show(struct foo *arg);
/* lib/lib.c */
#include <stdio.h>
#include "lib.h"
void show(struct foo *arg) {
printf("[%d]\n", arg->x);
}
So, you can get this to build all from go build main.go
if you have a main.go
like this:
package main
// #cgo CFLAGS: -I${SRCDIR}/lib
// #include "lib.c"
import "C"
func main() {
x := C.struct_foo{ x: 42 }
C.show(&x)
}
which works because we actually #include
the "C" source code for the library (which implicitly imports the lib/lib.h
file).
However, for more complicated libraries, you will likely need to build them as a separate, more normal C tool chain, pre-work build step:
$ cd lib
$ cc -c lib.c
$ ar cr libx.a lib.o
$ cd ..
and then use a different Go file: main2.go
:
package main
// #cgo CFLAGS: -I${SRCDIR}/lib
// #cgo LDFLAGS: -L${SRCDIR}/lib -lx
// #include "lib.h"
import "C"
func main() {
x := C.struct_foo{ x: 42 }
C.show(&x)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论