首页 > 解决方案 > 将 FILE 指针传递给 C 函数

问题描述

我的 C 函数获取 FILE 指针的地址(指向指针的指针,即FILE **fp)。我从 Go 调用这个方法。有人可以给我一个在 Go 中调用约定的示例代码行吗?

C 库代码(将创建.so 文件):

int fileOpen(char *filename, char* mode, FILE **fp){
*fp  = fopen (filename, mode);
 if (*fp ==NULL)
   return -1;
 return 0;
}
int fileread(FILE *fp,char *buff ){
        if((fp!=NULL)&&( fgets ( buff, 50, fp) != NULL ) )
        {
                return 0;
        }
  return -1;
}
int fileclose(FILE *fp){
  fclose(fp);
  return 0;
}

import "C"
type (
        fileptr C.FILE
)

func opencfile(name string, mode string) int {
        var fp *fileptr
        return (int)(C.fileOpen(C.CString(name), C.CString(mode), C.FILE(&fp)));
}

我收到错误

无法将 _cgoBase2(类型 **fileptr)转换为类型 _Ctype_struct__IO_FILE

问题:

  1. 这是调用C方法的正确方法吗?
  2. 如何从 Go 传递文件指针的地址?或如何解决上述错误。

被调用的“C”方法原型是:

int fileOpen(char *filename, char* mode, FILE **fp);

更新:这是我最新的代码:

C 代码(.c 文件)

#include "fileOp_lib.h"

int fileOpen(char *filename, char* mode, fileptr *out){
    FILE *fp  = fopen(filename, mode);
    if (fp == NULL) {
        *out = 0;
        return -1;
    }
    *out = (fileptr) fp;
    return 0;
}

int fileread(fileptr fp, char *buff){
    if( (fp != 0) && (fgets(buff, 50, (FILE*)fp) != NULL) )
        return 0;
    return -1;
}

int fileclose(fileptr fp){
    fclose((FILE*)fp);
    return 0;
}

头文件(.h 文件)

#include <stdio.h>
typedef unsigned int fileptr;
int fileOpen(char *filename, char* mode, fileptr *out);
//int fileread(FILE *fp,char *buff ); temp. commented
//int fileclose(FILE *fp);

去代码

package main

/*
#cgo LDFLAGS: -L./SAMPLE/ -lfileop
#include "fileOp_lib.h"
*/
import "C"
type (
        fileptr uintptr
)

func opencfile(name string, mode string) int {
        var fp fileptr;
        return (int)(C.fileOpen(C.CString(name), C.CString(mode), (&fp)));
}


func main(){
        var e int;
        e = opencfile("data.txt","r");
}

标签: cgo

解决方案


您可以从 Go 中正确调用原始 C 代码,而不是弄乱更多层。请参阅JimB 的评论或下面的示例。

请注意,原始的 C 代码......不是很好,并且考虑到除了 C 代码之外没有其他内容,使用 Go I/O 例程可能会更好,它更安全且更容易正确处理。大概你拥有的任何真正的 C 代码都要复杂得多。您遗漏的部分可能需要深入了解 C 和 Go 才能连接。

这是编译和运行的代码(并创建一个空的file.txt)。

package main

// #include <stdio.h>
// #include <stdlib.h>
// int fileOpen(char *filename, char *mode, FILE **fp) {
//      *fp = fopen(filename, mode);
//      if (*fp == NULL)
//              return -1;
//      return 0;
// }
//
// int fileread(FILE *fp, char *buff) {
//      if ((fp != NULL) && (fgets(buff, 50, fp) != NULL)) {
//              return 0;
//      }
//      return -1;
// }
//
// int fileclose(FILE *fp) {
//      fclose(fp);
//      return 0;
// }
import "C"

import (
        "fmt"
        "unsafe"
)

func opencfile(name string, mode string) (ret int, fp *C.FILE) {
        cname := C.CString(name)
        defer C.free(unsafe.Pointer(cname))
        cmode := C.CString(mode)
        defer C.free(unsafe.Pointer(cmode))
        ret = int(C.fileOpen(cname, cmode, &fp))
        return
}

func main() {
        ret, fp := opencfile("file.txt", "w")
        if ret >= 0 {
                defer C.fileclose(fp)
        }
        fmt.Printf("result of opencfile was %d\n", ret)
}

推荐阅读