zhangyuang / node-ffi-rs

Implement ffi in Node.js by Rust and NAPI
MIT License
160 stars 6 forks source link

关于创建void * 参数传递和结构体图片数据问题 #47

Open Hyliuz opened 3 months ago

Hyliuz commented 3 months ago
  1. 在当前1.0.79版本中是否有类似于ffi-napi 中 ref.refType(ref.types.void) 的方法,由于在迁移过程中发现,存在一些函数是需要创建一个指针,这个指针指向了函数内的一个属性的。这个指针在后续的过程中需要使用到。
  2. 关于结构体,同样存在一个 unsigned char data; 这个data 是一个图像数据 `ImageData { int width; int height; int channels; unsigned char data; };` 在ffi-napi 中 是通过base64 转换成 buffer 后,放入上面结构体中 通过 ImageData.ref() 传入到函数中
zhangyuang commented 3 months ago

关于指针的内容请查看DataType.External以及createPointer等相关api

Hyliuz commented 3 months ago

关于指针的内容请查看DataType.External以及createPointer等相关api

结果是通过参数传递,不是通过返回值,我看文档 const vp = createPointer({ paramsType: [DataType.Void], paramsValue: [''] }) 如果paramsValue 不设置值就会出现错误 load({ library: 'ESDK', funcName: 'elist', retType: DataType.I64, paramsType: [DataType.External], paramsValue: [vp], errno: true, }) 目前这一传入到paramsValue 中 会出现go object 错误 ffi-napi定义方式 ref.alloc(ref.refType(ref.types.void)) 这样传递

zhangyuang commented 3 months ago

1、DataType.Void不等于void*指针,一个代表空值一个代表通用类型指针,虽然也可以创建一个空值指针再写入值 2、paramsValue: unwrapPointer([vp]),用ts或者看文档 3、给出elist的函数签名

Hyliuz commented 3 months ago

1、DataType.Void不等于void*指针,一个代表空值一个代表通用类型指针,虽然也可以创建一个空值指针再写入值 2、paramsValue: unwrapPointer([vp]),用ts或者看文档 3、给出elist的函数签名

` typedef struct __edObject* BaseRef; typedef BaseRef ListRef;

unsigned long declspec(dllimport) stdcall elist(ListRef* ListRef) ` paramsValue: unwrapPointer([vp]) 这样子进程直接崩溃了

DataType.Void 是一个类型,在使用createPointer时候,我理解为创建一个该类型的指针,但是该方法一定需要传入值

zhangyuang commented 3 months ago

ListRef是结构体指针,你需要创建一个结构体指针传入

Hyliuz commented 3 months ago

__edObject 这个结构体是对外隐藏的,我只需要获取到这个句柄即可,构建一个结构体指针,我需要如何做,因为我并不知道这个结构里面有什么

zhangyuang commented 3 months ago

const vp = createPointer({ paramsType: [DataType.Void], paramsValue: [''] }) load({ library: "libsum", funcName: "getStruct2", retType: DataType.Void, paramsType: [ DataType.External ], paramsValue: vp

});

paramsValue: vp,试试

Hyliuz commented 3 months ago

const vp = createPointer({ paramsType: [DataType.Void], paramsValue: [''] }) load({ library: "libsum", funcName: "getStruct2", retType: DataType.Void, paramsType: [ DataType.External ], paramsValue: vp

});

paramsValue: vp,试试

这样的话进程直接崩溃了

Hyliuz commented 3 months ago

C++ 定义,_ _EdsObject * 是私有结构体,实际使用过程中只需要获取该指针句柄即可

typedef struct __EdsObject*    EdsBaseRef;
typedef  EdsBaseRef    EdsCameraListRef;
typedef long     EdsInt32;
typedef EdsUInt32    EdsError;

EdsError EDSAPI EdsGetCameraList( EdsCameraListRef*  outCameraListRef );
EdsError EDSAPI EdsGetChildCount( EdsBaseRef   inRef,EdsUInt32*   outCount );

第一种函数不使用void* 利用,如下

  let po = createPointer({
    paramsType: [DataType.WString],
    paramsValue: [""]
  })

load({
    library: 'EDSDK',
    funcName: 'EdsGetCameraList',
    retType: DataType.U64,
    paramsType: [DataType.External],
    paramsValue: po,
    errno: true,
  })

解决,但是这个指针怎么传递呢后续如下

load({
  library: 'EDSDK',
  funcName: 'EdsGetChildCount',
  retType: DataType.U64,
  paramsType: [DataType.External, DataType.External],
  paramsValue: [po,countNum],
  errno: true,
})

这样传递就会出现go object,括号去除就会出现params_type length is not equal with params_value length,

zhangyuang commented 3 months ago

const vp = createPointer({ paramsType: [DataType.Void], paramsValue: [''] })在语义上等价于ffi-napi中的ref.void,本质都是创建一个指针指向未初始化的数据。

createPointer({ paramsType: [DataType.WString], paramsValue: [""] })

创建的是指向字符串的指针,字符串数据在c语言中本身就是char*类型的指针。也就是说你上面的createPointer代码实际是创建了一个wchar**类型的指针。 另外createPointer返回的是数组,使用的时候用下标传入具体的元素这个说过很多次了。建议用ts来避免这种无谓的使用错误。