如何使用CGO获取realpath?

如何使用CGO获取realpath?,c,go,cgo,C,Go,Cgo,我有一点C代码,可以让realpath看起来正常工作: #include <limits.h> #include <stdio.h> #include <stdlib.h> char* getrpath(char *symlink) { char *symlinkpath = symlink; char actualpath [PATH_MAX]; symlink = realpath(symlinkpath, actualpath)

我有一点C代码,可以让realpath看起来正常工作:

#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;
}
#包括
#包括
#包括
char*getrpath(char*symlink){
char*symlinkpath=symlink;
字符实际路径[PATH_MAX];
symlink=realpath(symlinkpath,actualpath);
返回符号链接;
}
int main(int argc,char*argv[]){
char*symlinkpath=argv[0];
symlinkpath=getrpath(symlinkpath);
printf(“%s\n”,符号链接路径);
返回0;
}
我正在尝试为它创建一个包装器(仅用于学习目的):

主程序包
/*
#包括
#包括
#包括
char*getrpath(char*symlink){
char*symlinkpath=symlink;
字符实际路径[PATH_MAX];
symlink=realpath(symlinkpath,actualpath);
返回符号链接;
}
*/
输入“C”
进口(
“fmt”
“操作系统”
“路径”
“不安全”
)
func getArgv()字符串{
返回fmt.Sprintf(“./%s”,path.Base(os.Args[0]))
}
func main(){
slink:=C.CString(getArgv())
延迟C.free(不安全指针(slink))
ret:=C.getrpath(slink)
fmt.Println(C.GoString(翻新))
}

我无法将值返回到main()Golang函数中。如果我在C getrpath()函数中放置一个打印,它将打印路径。非常感谢任何提示。

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

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

char* getrpath(char *symlink) {
    char *actualpath = malloc(PATH_MAX);
    return realpath(symlink, actualpath);
}
或者更简单地说——因为如果为第二个参数传递NULL,则
getpath
被定义为
malloc
内存本身:

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

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

OK最终得到了它,但不得不直接调用C.realpath:

package main

/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
    "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”
进口(
“fmt”
“不安全”
)
func currentDir()[]字节{
返回[]字节{0x2e,0x2f}
}
func rpath()字符串{
relativePath:=currentDir()
限制:=生成([]字节,C.PATH_MAX)
slink:=生成([]字节,len(相对路径)+1)
副本(链接、相对路径)
C.realpath(
(*C.char)(不安全的.Pointer(&slink[0]),
(*C.char)(不安全的.Pointer(&limit[0]))
返回C.GoString((*C.char)(不安全的.Pointer(&limit[0]))
}
func main(){
fmt.Println(rpath())
}

我也不检查它是否返回任何东西。。。最好检查一下是否真的使用了它。

太棒了。很好的解释不幸的是,我仍然无法从main()Golang函数打印
char *getrpath(char *symlink) {
    return realpath(symlink, 0);
}
package main

/*
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
    "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())
}