doukang5966907 2018-11-20 15:14
浏览 88
已采纳

通过Node调用golang函数时无法打开文件

I followed the tutorial in https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf to make my node app able to call golang function. The provided example works like a charm.
I do, however, unable it to implement in another scenario. Here I want to open a file by providing only it's absolute path and call the Go's function, but it always told me that it can't find the file due to no such file. I'm trying to run it directly in Go and it works!
Am I doing it wrong or is it an actual bug/unfinished feature?

Here is the golang source that I've built to c-style lib :

package main

import "C"

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {}

//export ReadSomething
func ReadSomething(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        log.Fatal(err)
    }

    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }

}

I built it with this command :

go build -buildmode=c-shared -o simpleread.so main.go

In case you're wondering what's the header output :

/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */

#line 1 "cgo-builtin-prolog"

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */
/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern void ReadSomething(GoString p0);

#ifdef __cplusplus
}
#endif

And then, below is how I call it via Node. I give the comment on the line where the error generated :

var ref = require("ref")
var ffi = require("ffi-napi")
var Struct = require("ref-struct")
var ArrayType = require("ref-array")
var LongArray = ArrayType(ref.types.longlong);

  var GoString = Struct({
    p: "string",
    n: "longlong"
  });

  var simpleRead = ffi.Library("./simpleread.so", {
    ReadSomething: ["void", [GoString]]
  });

  // error here, can't open the specified file
  simpleRead.ReadSomething("/home/ivan/Documents/crashsite/node-go-crossfire/simpletext.txt")

I'm running it on Ubuntu 18.04 64bit.

  • 写回答

1条回答 默认 最新

  • douhe8981 2018-11-20 18:22
    关注

    Remember that strings in Go are like slices. They are composed of a pointer to the backing data and the length. This is why in your code, GoString is defined as:

    var GoString = Struct({
        p: "string",  // pointer
        n: "longlong" // length
    });
    

    I'd recommend you define a function for creating a GoString e.g.

    function NewGoString(str) {
        return new GoString({p: str, n: str.length})
    }
    

    Which you can use in your code like:

    var simpleRead = ffi.Library("./simpleread.so", {
        ReadSomething: ["void", [GoString]]
    });
    
    simpleRead.ReadSomething(NewGoString("/path/to/your/file"))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?
  • ¥15 关于#vue.js#的问题:修改用户信息功能图片无法回显,数据库中只存了一张图片(相关搜索:字符串)
  • ¥15 texstudio的问题,