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

主要修改:

  1. 在C函数中添加了缺失的分号
  2. 添加了内存分配失败检查
  3. 正确处理了realpath()返回NULL的情况
  4. 在Go代码中添加了对返回指针的NULL检查
  5. 使用defer确保释放C函数分配的内存

示例输出:

/home/user/projects/myapp

如果遇到权限问题或路径不存在,程序会输出"Failed to get real path"。

回到顶部