首页 > 解决方案 > 如何使用 CGO 获得 realpath?

问题描述

我有一些 C 代码来获取似乎有效的真实路径:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

char* getrpath(char *symlink) {
    char *symlinkpath = symlink;
    char actualpath [PATH_MAX];
    symlink = realpath(symlinkpath, actualpath);
    return symlink;
}


int main(int argc, char *argv[]) {
    char *symlinkpath = argv[0];
    symlinkpath = getrpath(symlinkpath);
    printf("%s\n", symlinkpath);
    return 0;
}

我正在尝试为它创建一个包装器(仅用于学习目的):

package main

/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

char* getrpath(char *symlink) {
    char *symlinkpath = symlink;
    char actualpath [PATH_MAX];
    symlink = realpath(symlinkpath, actualpath);
    return symlink;
}
*/
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))
}

我无法将值恢复到 main() Golang 函数中。如果我在 C getrpath() 函数中打印,它会打印路径。非常感谢任何提示。

标签: cgocgo

解决方案


问题是您的 C 函数正在返回分配在 C 堆栈上的内存,这是 C 中未定义的行为(并且在实践中可能导致垃圾值):

char* getrpath(char *symlink) {
    char *symlinkpath = symlink;
    char actualpath [PATH_MAX];
    symlink = realpath(symlinkpath, actualpath);
    return symlink;
}

您需要返回堆分配的内存。像这样:

char* getrpath(char *symlink) {
    char *actualpath = malloc(PATH_MAX);
    return realpath(symlink, actualpath);
}

或者更简单地说——因为如果你为第二个参数传入 NULL ,它就getpath被定义为内存本身:malloc

char *getrpath(char *symlink) {
    return realpath(symlink, 0);
}

(我还删除了您介绍的变量,但这不是编辑的重要部分)。


推荐阅读