Golang中如何从C函数返回char*(CGO问题)
Golang中如何从C函数返回char*(CGO问题)
我无法从 getrpath() 函数返回字符指针。我知道在下面的代码中调用了 C 函数,因为 printf 可以打印出 realpath。但我似乎无法将 char* 返回到 main() 函数中。
有什么建议吗?谢谢。
package main
/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char* getrpath(char *symlink) {
char *actualpath = malloc(PATH_MAX);
return realpath(symlink, actualpath)
}
*/
import "C"
import (
"fmt"
"os"
"path"
"unsafe"
)
func getArgv() string {
return fmt.Sprintf("./%s", path.Base(os.Args[0]))
}
func main() {
slink := C.CString(getArgv())
defer C.free(unsafe.Pointer(slink))
ret := C.getrpath(slink)
fmt.Println(C.GoString(ret))
}
更多关于Golang中如何从C函数返回char*(CGO问题)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
4 回复
你所说的“无法”是什么意思?是遇到错误了吗?
更多关于Golang中如何从C函数返回char*(CGO问题)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
不……完全没有错误。它编译得很好,但在 main() 函数中什么也不打印……只输出一个空行。有什么想法吗?我肯定花了几个小时研究不同的方法,试图将指针返回到 main 中……Stack Overflow 和 Golang Google Groups……实际上我做了几个不同的版本,但结果都一样。
好的,我最终解决了这个问题,但只能通过直接调用 realpath 函数来实现:
package main
/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
"bytes"
"fmt"
"unsafe"
)
func currentDir() []byte {
return []byte{0x2e, 0x2f}
}
func rpath() string {
relativePath := currentDir()
limit := make([]byte, C.PATH_MAX)
slink := make([]byte, len(relativePath)+1)
copy(slink, relativePath)
C.realpath(
(*C.char)(unsafe.Pointer(&slink[0])),
(*C.char)(unsafe.Pointer(&limit[0])))
return C.GoString((*C.char)(unsafe.Pointer(&limit[0])))
}
func main() {
fmt.Println(rpath())
}
问题在于你的C函数缺少分号,并且需要正确处理内存管理。以下是修正后的代码:
package main
/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char* getrpath(char *symlink) {
char *actualpath = malloc(PATH_MAX);
if (actualpath == NULL) {
return NULL;
}
char *result = realpath(symlink, actualpath);
if (result == NULL) {
free(actualpath);
return NULL;
}
return actualpath;
}
*/
import "C"
import (
"fmt"
"os"
"path"
"unsafe"
)
func getArgv() string {
return fmt.Sprintf("./%s", path.Base(os.Args[0]))
}
func main() {
slink := C.CString(getArgv())
defer C.free(unsafe.Pointer(slink))
ret := C.getrpath(slink)
if ret == nil {
fmt.Println("Failed to get real path")
return
}
defer C.free(unsafe.Pointer(ret))
fmt.Println(C.GoString(ret))
}
主要修改:
- 在C函数中添加了缺失的分号
- 添加了内存分配失败检查
- 正确处理了
realpath()返回NULL的情况 - 在Go代码中添加了对返回指针的NULL检查
- 使用
defer确保释放C函数分配的内存
示例输出:
/home/user/projects/myapp
如果遇到权限问题或路径不存在,程序会输出"Failed to get real path"。

