在 Golang 包中编译 CGO 文件
Compiling CGO files in Golang package
我正在尝试使用 CGO 将 C 文件与 Golang 包捆绑在一起。按照此处的说明操作:
https://karthikkaranth.me/blog/calling-c-code-from-go/
http://akrennmair.github.io/golang-cgo-slides/#1
我收到这个错误:
# main
src/main/main.go:16:8: could not determine kind of name for C.free
src/main/main.go:23:10: could not determine kind of name for C.greet
结构如下:
main.go
看起来像:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "genericc/greeter.h"
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}
我 运行 test.sh 构建它:
#!/usr/bin/env bash
dir="$(cd `dirname "[=12=]"` && pwd)"
export GOPATH="$dir"
cd "$dir"
export CGOFILES=main
go install main
但是当我 运行 bash 脚本时,我得到了那个错误。
我按照说明操作:
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"
or
/*
#include <stdio.h>
#include <errno.h>
*/
import "C"
例如,
gocbuf.go
:
package main
import (
"fmt"
"unsafe"
)
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int printData(unsigned char *data) {
return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data);
}
*/
import "C"
func main() {
// Allocate C data buffer.
width, height := 8, 2
lenData := width * height
// add string terminating null byte
cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar))
// When no longer in use, free C allocations.
defer C.free(unsafe.Pointer(cData))
// Go slice reference to C data buffer,
// minus string terminating null byte
gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData]
// Write and read cData via gData.
for i := range gData {
gData[i] = '.'
}
copy(gData[0:], "Data")
gData[len(gData)-1] = 'X'
fmt.Printf("gData: %d %q\n", len(gData), gData)
C.printData(cData)
}
输出:
$ go run gocbuf.go
gData: 16 "Data...........X"
cData: 16 "Data...........X"
$
你的代码组织对我来说毫无意义。
您应该有包 greeter
,它通过 cgo
包装了 C
函数。例如,
src
└── greeter
├── greeter.c
├── greeter.go
└── greeter.h
有框架文件
greeter.go
:
package greeter
/*
#include "greeter.h"
*/
import "C"
greeter.c
:
#include "greeter.h"
greeter.h
/* C header file */
要安装 greeter
包,只需使用 go install
。
不要使用相对路径。不要使用 bash 脚本。
感谢@peterSO,这是有效的:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "../genericc/greeter.h"
// #include "../genericc/greeter.c" // ! no whitespace after this line
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}
我正在尝试使用 CGO 将 C 文件与 Golang 包捆绑在一起。按照此处的说明操作:
https://karthikkaranth.me/blog/calling-c-code-from-go/
http://akrennmair.github.io/golang-cgo-slides/#1
我收到这个错误:
# main src/main/main.go:16:8: could not determine kind of name for C.free src/main/main.go:23:10: could not determine kind of name for C.greet
结构如下:
main.go
看起来像:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "genericc/greeter.h"
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}
我 运行 test.sh 构建它:
#!/usr/bin/env bash
dir="$(cd `dirname "[=12=]"` && pwd)"
export GOPATH="$dir"
cd "$dir"
export CGOFILES=main
go install main
但是当我 运行 bash 脚本时,我得到了那个错误。
我按照说明操作:
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"
or
/* #include <stdio.h> #include <errno.h> */ import "C"
例如,
gocbuf.go
:
package main
import (
"fmt"
"unsafe"
)
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int printData(unsigned char *data) {
return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data);
}
*/
import "C"
func main() {
// Allocate C data buffer.
width, height := 8, 2
lenData := width * height
// add string terminating null byte
cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar))
// When no longer in use, free C allocations.
defer C.free(unsafe.Pointer(cData))
// Go slice reference to C data buffer,
// minus string terminating null byte
gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData]
// Write and read cData via gData.
for i := range gData {
gData[i] = '.'
}
copy(gData[0:], "Data")
gData[len(gData)-1] = 'X'
fmt.Printf("gData: %d %q\n", len(gData), gData)
C.printData(cData)
}
输出:
$ go run gocbuf.go
gData: 16 "Data...........X"
cData: 16 "Data...........X"
$
你的代码组织对我来说毫无意义。
您应该有包 greeter
,它通过 cgo
包装了 C
函数。例如,
src
└── greeter
├── greeter.c
├── greeter.go
└── greeter.h
有框架文件
greeter.go
:
package greeter
/*
#include "greeter.h"
*/
import "C"
greeter.c
:
#include "greeter.h"
greeter.h
/* C header file */
要安装 greeter
包,只需使用 go install
。
不要使用相对路径。不要使用 bash 脚本。
感谢@peterSO,这是有效的:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "../genericc/greeter.h"
// #include "../genericc/greeter.c" // ! no whitespace after this line
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}