在Golang包中编译CGO文件

I am trying to use CGO to bundle C files with a Golang package. Following instructions here:

https://karthikkaranth.me/blog/calling-c-code-from-go/

http://akrennmair.github.io/golang-cgo-slides/#1

https://golang.org/cmd/cgo/

I am getting this error:

# 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

here is the structure:

enter image description here

main.go just looks like:

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))
}

and I run test.sh to build it:

#!/usr/bin/env bash

dir="$(cd `dirname "$0"` && pwd)"
export GOPATH="$dir"

cd "$dir"

export CGOFILES=main
go install main

but when I run the bash script I get that error.

cgo

2个回答

I follow the instructions:

Command cgo

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"

For example,

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\"
", (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
", len(gData), gData)
    C.printData(cData)
}

Output:

$ go run gocbuf.go
gData: 16 "Data...........X"
cData: 16 "Data...........X"
$ 

Your code organization makes no sense to me.

You should have package greeter, which wraps C functions via cgo. For example,

src
└── greeter
    ├── greeter.c
    ├── greeter.go
    └── greeter.h

with skeleton files

greeter.go:

package greeter

/*
#include "greeter.h"
*/
import "C"

greeter.c:

#include "greeter.h"

greeter.h

/* C header file */

To install the greeter package, simply use go install.

Don't use relative paths. Don't use bash scripts.

doulianglou0898
doulianglou0898 要使用bash脚本,还要如何设置$ GOPATH? 我把我的围棋项目放在fs的各个地方。
接近 2 年之前 回复
dongshen7407
dongshen7407 是的,您是对的,但是我正在编写main / main.go来测试我的库,就好像我是最终用户一样,看到了吗?
接近 2 年之前 回复
douwu7168
douwu7168 您的代码组织对我来说毫无意义。 请参阅我的修订答案。
接近 2 年之前 回复
douzhan1031
douzhan1031 谢谢,我让它正常工作并发布了答案,如果您知道使用../genericc/greeter.c,lmk的相对路径以外的更好方法
接近 2 年之前 回复
dongzhao3040
dongzhao3040 是的,空白行确实有所作为。 现在无法找到genericc / greeter.h。
接近 2 年之前 回复

Thanks to @peterSO, this is what worked:

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))
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐