Koromix / koffi

Fast and easy-to-use C FFI module for Node.js
https://koffi.dev/
MIT License
146 stars 3 forks source link

How to define void ** return handle problem #172

Closed Hyliuz closed 2 weeks ago

Hyliuz commented 2 weeks ago

C Typedef

enum ASF_DetectMode{
    ASF_DETECT_MODE_VIDEO = 0x00000000,     
    ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF
};

enum ASF_OrientPriority {
    ASF_OP_0_ONLY = 0x1,        
    ASF_OP_90_ONLY = 0x2,       
    ASF_OP_270_ONLY = 0x3,      
    ASF_OP_180_ONLY = 0x4,      
    ASF_OP_ALL_OUT = 0x5
};

typedef signed      int         MInt32;
typedef void*                   MHandle;
typedef long                    MLong;
typedef MLong                   MRESULT;

MRESULT ASFInitEngine(
    ASF_DetectMode      detectMode,                 
    ASF_OrientPriority  detectFaceOrientPriority,
    MInt32              detectFaceMaxNum,       
    MInt32              combinedMask,
    MHandle*            hEngine  [out] handle
);

koffi Type


const ASF_DetectMode = koffi.alias('DetectMode', 'int');
const DetectMode = {
  ASF_DETECT_MODE_VIDEO: 0x00000000,    
  ASF_DETECT_MODE_IMAGE: 0xFFFFFFFF 
}
const ASF_OrientPriority = koffi.alias('OrientPriority', 'int');
const OrientPriority = {
      ASF_OP_0_ONLY: 0x1,   
      ASF_OP_90_ONLY: 0x2,  
      ASF_OP_270_ONLY: 0x3, 
      ASF_OP_180_ONLY: 0x4,     
      ASF_OP_ALL_OUT: 0x5       
}
const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
const MHandle = koffi.out(koffi.pointer(koffi.pointer(koffi.types.void)));
    let ASFInitEngine = dll.func('ASFInitEngine', TypeDef.MRESULT, [ASF_DetectMode, ASF_OrientPriority, koffi.types.int, koffi.types.int, MHandle]);

let pEngine = [null];
let initCode = ASFInitEngine(
  DetectMode.ASF_DETECT_MODE_IMAGE,
  OrientPriority.ASF_OP_0_ONLY,
  5,
  mask,
  koffi.alias('pEngine', HANDLE),
);
console.log(initCode);

The returned result reminds me that there is an error in the parameter, and I am confused about how to define void ** return handle. ref-napi Type

const typedef = {};
typedef.MHandle = ref.refType(ref.types.void);

 let pEngine = ref.alloc(TypeDef.MHandle);
 let mask =
      TypeDef.ASF_FACE_DETECT |
      TypeDef.ASF_FACERECOGNITION |
      TypeDef.ASF_IMAGEQUALITY |
      TypeDef.ASF_AGE |
      TypeDef.ASF_GENDER |
      TypeDef.ASF_LIVENESS |
      TypeDef.ASF_IR_LIVENESS |
      TypeDef.ASF_MASKDETECT;
    let initCode = dll.ASFInitEngine(
      TypeDef.ASF_DETECT_MODE_IMAGE,
      TypeDef.ASF_OP_0_ONLY,
      5,
      mask,
      pEngine
    );
 pEngine = pEngine.deref()

Here the result is correct
SishirAdhikari commented 2 weeks ago

const DetectMode = { ASF_DETECT_MODE_VIDEO: 0x00000000,
ASF_DETECT_MODE_IMAGE: 0xFFFFFFFF } const OrientPriority = { ASF_OP_0_ONLY: 0x1,
ASF_OP_90_ONLY: 0x2,
ASF_OP_270_ONLY: 0x3, ASF_OP_180_ONLY: 0x4,
ASF_OP_ALL_OUT: 0x5
} const ASF_DetectMode = koffi.alias('ASF_DetectMode', 'uint32_t'); const ASF_OrientPriority = koffi.alias('ASF_OrientPriority', 'uint16_t'); const MInt32 = koffi.alias('MInt32', 'int32_t'); const MHandle = koffi.alias('MHandle', 'void *'); const MResult = koffi.alias('MResult', 'long');

const ASFInitEngine = dll.func('MRESULT ASFInitEngine(ASF_DetectMode detectMode,ASF_OrientPriority detectFaceOrientPriority,MInt32 detectFaceMaxNum,MInt32 combinedMask,Out MHandle *hEngine)'); let pEngine = [null]; let mask = 0; let initCode = ASFInitEngine( DetectMode.ASF_DETECT_MODE_IMAGE, OrientPriority.ASF_OP_0_ONLY, 5, mask, pEngine); console.log(initCode, pEngine[0]);

Hyliuz commented 2 weeks ago

Thanks, I've solved it, it's actually defined like this koffi.out(koffi.pointer(koffi.opaque(), 2)),

There may be a memory problem with the koffi, I'm troubleshooting it, I'm transferring image data to a function in the sdk and it's caused by the image pass in image step. This is caused by the image pass in step, I tried the step where I just enter the width without using the width channel, he succeeded, but after that the results appear incorrect, passing in the width channel sdk prompts me that I don't have enough memory!

Hyliuz commented 2 weeks ago

Koffi define

const typedef = {};
typedef.koffi = koffi;
typedef.MLong = koffi.types.long;
typedef.MFloat = koffi.types.float;
typedef.MDouble = koffi.types.double;
typedef.MByte = koffi.types.uchar;
typedef.MWord = koffi.types.ushort;
typedef.MDWord = koffi.types.uint;
typedef.MHandle = koffi.pointer(koffi.types.void);
typedef.MChar = koffi.types.char;
typedef.MBool = koffi.types.long;
typedef.MVoid = koffi.types.void;
typedef.MPVoid = koffi.pointer(koffi.types.void);
typedef.MPChar = koffi.pointer(koffi.types.char);
typedef.MShort = koffi.types.short;
typedef.MPCChar = 'const char*';
typedef.MHandle = koffi.pointer(koffi.types.void);

typedef.MRESULT = typedef.MLong;
typedef.MCOLORREF = typedef.MDWord;

typedef.MInt8 = koffi.types.char;
typedef.MUInt8 = koffi.types.uchar;
typedef.MInt16 = koffi.types.short;
typedef.MUInt16 = koffi.types.ushort;
typedef.MInt32 = koffi.types.int;
typedef.MUInt32 = koffi.types.uint;

typedef.ASF_OrientCode = typedef.MInt32;

typedef.__tag_rect = koffi.struct('__tag_rect', {
  left: typedef.MInt32,
  top: typedef.MInt32,
  right: typedef.MInt32,
  bottom: typedef.MInt32,
});
typedef.MRECT = typedef.__tag_rect;

typedef.ASF_FaceDataInfo = koffi.struct('ASF_FaceDataInfo', {
  data: koffi.array(koffi.types.uint8_t, koffi.sizeof(koffi.types.uintptr_t)),
  dataSize: typedef.MInt32
});

typedef.LPASF_FaceDataInfo = koffi.pointer(typedef.ASF_FaceDataInfo);

typedef.ASF_FaceAttributeInfo = koffi.struct('ASF_FaceAttributeInfo', {
  wearGlasses: koffi.pointer(typedef.MInt32),
  leftEyeOpen: koffi.pointer(typedef.MInt32),
  rightEyeOpen: koffi.pointer(typedef.MInt32),
  mouthClose: koffi.pointer(typedef.MInt32),
})

typedef.LPASF_FaceAttributeInfo = koffi.pointer(typedef.ASF_FaceAttributeInfo);

typedef.ASF_Face3DAngleInfo = koffi.struct('ASF_Face3DAngleInfo', {
  roll: koffi.pointer(typedef.MFloat),
  yaw: koffi.pointer(typedef.MFloat),
  pitch: koffi.pointer(typedef.MFloat)
});

typedef.LPASF_Face3DAngleInfo = koffi.pointer(typedef.ASF_Face3DAngleInfo);

typedef.ASF_MultiFaceInfo = koffi.struct('ASF_MultiFaceInfo', {
  faceNum: typedef.MInt32,
  faceRect: koffi.pointer(typedef.MRECT),
  faceOrient: koffi.pointer(typedef.MInt32),
  faceId: koffi.pointer(typedef.MInt32), 
  faceDataInfoList: typedef.LPASF_FaceDataInfo,
  faceIsWithinBoundary: koffi.pointer(typedef.MInt32),
  foreheadRect: koffi.pointer(typedef.MRECT),
  faceAttributeInfo: typedef.ASF_FaceAttributeInfo,
  face3DAngleIn: typedef.ASF_Face3DAngleInfo 
});

typedef.LPASF_MultiFaceInfo = koffi.pointer(typedef.ASF_MultiFaceInfo);

function

const parseImage = async (imgFile, color = 1) => {
  return Jimp.read(imgFile).then((image) => {
    let cutImg = cv.matFromImageData(image.bitmap);
    let cvSize = new cv.Size(image.bitmap.width - (image.bitmap.width % 4), image.bitmap.height);
    cv.resize(cutImg, cutImg, cvSize, 0, 0, cv.INTER_NEAREST);
    if (cutImg.channels() === 4) {
      cv.cvtColor(cutImg, cutImg, cv.COLOR_RGBA2BGR)
    } else if (cutImg.channels() === 3) {
      cv.cvtColor(cutImg, cutImg, cv.COLOR_RGB2BGR)
    }
    let asvl = {};

    switch (color) {
      case 1:
        console.log(">>>>>>>>>", cutImg.channels())
        asvl.u32PixelArrayFormat = TypeDef.ASVL_PAF_RGB24_B8G8R8;
        asvl.i32Width = cutImg.cols;
        asvl.i32Height = cutImg.rows;
        asvl.ppu8Plane = [cutImg.data, 0, 0, 0];
        asvl.pi32Pitch = [cutImg.step[0], 0, 0, 0]
        break;
    }
    return asvl;
  });

}

  let mask =
      TypeDef.ASF_FACE_DETECT |
      TypeDef.ASF_FACERECOGNITION |
      TypeDef.ASF_IMAGEQUALITY |
      TypeDef.ASF_AGE |
      TypeDef.ASF_GENDER |
      TypeDef.ASF_LIVENESS |
      TypeDef.ASF_IR_LIVENESS |
      TypeDef.ASF_MASKDETECT;
    let ASFInitEngine = dll.func('ASFInitEngine', TypeDef.MRESULT, [koffi.types.int8, koffi.types.int8, TypeDef.MInt32, TypeDef.MInt32, koffi.out(koffi.pointer(TypeDef.MHandle))]);
    let pEngine = [null]
    let initCode = await ASFInitEngine(
      TypeDef.ASF_DETECT_MODE_IMAGE,
      TypeDef.ASF_OP_0_ONLY,
      5,
      mask,
      pEngine
    );
    console.log(initCode);
    let HWD = pEngine[0];

    let img = await Jimp.read("C:\\Users\\Desktop\\in.png");
    let imageBuffer = await img.getBufferAsync("image/png");
    let asvl = await parseImage(imageBuffer, 1)
    let faceInfo = {};
    let ASFDetectFacesEx = dll.func('ASFDetectFacesEx', TypeDef.MRESULT, [TypeDef.MHandle, 'ASVLOFFSCREEN *', '_Out_ ASF_MultiFaceInfo*', koffi.types.int8]);

    const faces = await ASFDetectFacesEx(
      HWD,
      asvl,
      faceInfo,
      TypeDef.ASF_DETECT_MODEL_RGB
    );
    debugger
    console.log(faces);

    let combinedMask = TypeDef.ASF_LIVENESS;
    let ASFProcessEx = dll.func('ASFProcessEx', TypeDef.MRESULT, [TypeDef.MHandle, TypeDef.LPASVLOFFSCREEN, TypeDef.LPASF_MultiFaceInfo, TypeDef.MInt32]);
    let processCode = await ASFProcessEx(HWD, asvl, faceInfo, combinedMask);
    console.log(processCode);
   It keeps telling me there's not enough memory.

C-Function

typedef long                    MLong;
typedef float                   MFloat;
typedef double                  MDouble;
typedef unsigned char           MByte;
typedef unsigned short          MWord;  
typedef unsigned int            MDWord; 
typedef void*                   MHandle;
typedef char                    MChar;
typedef long                    MBool;
typedef void                    MVoid;
typedef void*                   MPVoid;
typedef char*                   MPChar;
typedef short                   MShort;
typedef const char*             MPCChar;
typedef MLong                   MRESULT;
typedef MDWord                  MCOLORREF; 
typedef signed      char        MInt8;
typedef unsigned    char        MUInt8;
typedef signed      short       MInt16;
typedef unsigned    short       MUInt16;
typedef signed      int         MInt32;
typedef unsigned    int         MUInt32;

enum ASF_DetectModel{
    ASF_DETECT_MODEL_RGB = 0x1  
};

enum ASF_DetectMode{
    ASF_DETECT_MODE_VIDEO = 0x00000000,     
    ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF
};

enum ASF_OrientPriority {
    ASF_OP_0_ONLY = 0x1,        
    ASF_OP_90_ONLY = 0x2,       
    ASF_OP_270_ONLY = 0x3,      
    ASF_OP_180_ONLY = 0x4,      
    ASF_OP_ALL_OUT = 0x5
};

typedef struct{
        MInt32*             wearGlasses;        
        MInt32*             leftEyeOpen;       
        MInt32*             rightEyeOpen;       
        MInt32*             mouthClose;         
} ASF_FaceAttributeInfo, *LPASF_FaceAttributeInfo;

typedef struct{
        MFloat* roll;
        MFloat* yaw;
        MFloat* pitch;
}ASF_Face3DAngleInfo, *LPASF_Face3DAngleInfo;

typedef struct __tag_rect{
    MInt32 left;
    MInt32 top;
    MInt32 right;
    MInt32 bottom;
} MRECT, *PMRECT;

typedef struct __tag_ASVL_OFFSCREEN
{
    MUInt32 u32PixelArrayFormat;
    MInt32  i32Width;
    MInt32  i32Height;
    MUInt8* ppu8Plane[4];
    MInt32  pi32Pitch[4];
}ASVLOFFSCREEN, *LPASVLOFFSCREEN;

typedef struct{
        MInt32                  faceNum;                
        MRECT*                  faceRect;              
        MInt32*                 faceOrient;             
        MInt32*                 faceID;                
        LPASF_FaceDataInfo      faceDataInfoList;       
        MInt32*                 faceIsWithinBoundary;  
        MRECT*                  foreheadRect;         
        ASF_FaceAttributeInfo   faceAttributeInfo;      
        ASF_Face3DAngleInfo     face3DAngleInfo;       
}ASF_MultiFaceInfo, *LPASF_MultiFaceInfo;

typedef struct{
        MPVoid      data;       
        MInt32      dataSize;   
} ASF_FaceDataInfo, *LPASF_FaceDataInfo;

MRESULT ASFInitEngine(
        ASF_DetectMode      detectMode,         // [in]
        ASF_OrientPriority  detectFaceOrientPriority,   // [in]
        MInt32              detectFaceMaxNum,   // [in]
        MInt32              combinedMask,       // [in]
        MHandle*            hEngine             // [out] return handle
);
MRESULT ASFDetectFacesEx(
        MHandle             hEngine,    // [in] 
        LPASVLOFFSCREEN     imgData,    // [in]
        LPASF_MultiFaceInfo detectedFaces,// [out] 
        ASF_DetectModel     detectModel = ASF_DETECT_MODEL_RGB  // [in]
);
MRESULT ASFProcessEx(
        MHandle             hEngine,// [in] 
        LPASVLOFFSCREEN     imgData,// [in] 
        LPASF_MultiFaceInfo detectedFaces,// [in]
        MInt32              combinedMask// [in] 
);

ASFInitEngine, ASFDetectFacesEx s are correct, I can parse the values correctly, but when I use ASFProcessEx, I keep getting the message that there is not enough memory, but when I use ffi-napi/ref-napi, it's normal, I'm not sure what the problem is, so I'm going to try it again when I modify the parseImage>asvl.pi32Pitch = asvl.i32Width, then it can be executed normally, but the result is obviously wrong, actually it should be widthStep. I am sure that in ffi-napi/ref-napi, it is possible to get the result normally.

Hyliuz commented 2 weeks ago

Problem found, due to the large size of the first parameter of the ASFInitEngine, it must be defined using the koffi.types.uint32_t type.

 let ASFInitEngine = dll.func("ASFInitEngine", TypeDef.MRESULT, [koffi.types.uint32_t, TypeDef.MInt32, TypeDef.MInt32, TypeDef.MInt32, koffi.out(koffi.pointer(TypeDef.MHandle))]);
Koromix commented 1 week ago

Sorry, I'm not sure I understand if things are fixed now. What about the memory problem you had? Does everything work now?

Hyliuz commented 1 week ago

Thank you for your reply, the problem has been solved

---Original--- From: "Niels @.> Date: Fri, Jul 12, 2024 17:48 PM To: @.>; Cc: @.>;"State @.>; Subject: Re: [Koromix/koffi] How to define void ** return handle problem(Issue #172)

Sorry, I'm not sure I understand if things are fixed now. What about the memory problem you had? Does everything work now?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.Message ID: @.***>