This Question is Possibly Answered

1 "correct" answer available (4 pts) 1 "helpful" answer available (2 pts)
4 Replies Last post: Nov 2, 2009 5:26 PM by Serge Piletsky  
Monty Charlton   2 posts since
Oct 8, 2009
Currently Being Moderated

Oct 8, 2009 7:43 AM

Resized ‘struct’ on the heap

Hello all,

 

I'm calling a couple of C functions that take a parameter (pEvent) which is a resized struct on the heap. The C side of this code works fine, but I can't seem to figure out how to mimick it correctly. Can anyone help?

 

I've tried a million different combinations for dp_device_event_t.Data (which I think is my problem), but nothing seems to work right.

 

/* header */
#define FT_BOOL int
#define FT_FALSE 0
#define FT_TRUE 1
typedef unsigned char FT_BYTE;
#define DP_UID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
((dp_uid_t){a, b, c, {d0, d1, d2, d3, d4, d5, d6, d7}})
#define DP_UID_NULL DP_UID(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
typedef enum
{
  FT_PRE_REG_FTR,
  FT_REG_FTR,
  FT_VER_FTR,
}
FT_FTR_TYPE;
typedef struct {
    uint32_t uData1;
    uint16_t usData2;
    uint16_t usData3;
    uint8_t  ubData4[8];
} dp_uid_t;
 
typedef struct {
    uint32_t nEvent;
    dp_uid_t DeviceUid;
    uint32_t uDataSize;
    uint8_t  Data[1];
} dp_device_event_t;
 
/*
 * Parameters:
 *  pDevUID  UID of the device of interest.
 *  ppEvent  Pointer to pointer to memory wich receive information about event.
 *            Memory is allocated inside DPFPGetEvent(). To release memory application
 *            should call DPFPBufferFree().
 *  uTimeout  timeout in milliseconds. If uTimeout is 0 than function returns immidiately.
 *            If uTimeout is DP_TIMEOUT_INFINITE than function returns only if application
 *            calls DPFPUnsubscribe() from a different thread.
 * Returns:
 *  0 on success
 */
 
DPFP_STDAPI DPFPGetEvent(dp_uid_t* pDevUid, dp_device_event_t** ppEvent, uint32_t uTimeoutMsec);
 
 
FX_DLL_INTERFACE FT_RETCODE
FX_getFeaturesLen(
  IN  FT_FTR_TYPE featureSetPurpose,
  OUT int* recommendedFeatureSetSize, /* Pointer to the memory receiving the size of the buffer */
  OUT int* minimumFeatureSetSize);    /* Pointer to the memory receiving the minimum size */
 
FX_DLL_INTERFACE FT_RETCODE
FX_extractFeatures(
  IN  FT_HANDLE fxContext,                 /* Handle to the feature extraction context */
  IN  int imageSize,                       /* Size of the fingerprint image obtained from the reader, in bytes */
  IN  const FT_IMAGE_PTC imagePt,          /* Pointer to the buffer containing the image */
  IN  FT_FTR_TYPE featureSetPurpose,       /* Feature set purpose. */
  IN  int featureSetSize,                  /* feature set size. This parameter is the size, in bytes */
  OUT FT_BYTE* featureSet,                 /* Pointer to the location of the buffer receiving the feature set */
  OUT FT_IMG_QUALITY_PT imageQualityPt,    /* Pointer to the buffer containing information about the quality of ...*/
  OUT FT_FTR_QUALITY_PT featuresQualityPt, /* Pointer to the buffer containing information about the quality of ...*/
  OUT FT_BOOL* featureSetCreated);         /* Pointer to the memory receiving the value of ...*/
/* end header */
 

 

 

/* C code */
 
dp_device_event_t* pEvent = NULL;
int32_t res = DPFPGetEvent(pIdDev, &pEvent, (uint32_t)(8000L));
 
FT_BYTE* pFeatures = NULL;
int nMinLen = 0, nLen = 0;
 
retval = FX_getFeaturesLen(nFtrType, &nLen, &nMinLen);
if(FT_OK == retval) pFeatures = malloc(nLen);
 
FT_BOOL bOk = 0;
FT_RETCODE tres = FX_extractFeatures(hFxContext, pEvent->uDataSize, pEvent->Data, nFtrType, nLen, pFeatures, pImgQ, pFtrQ, &bOk);
 
 
 
 

 

 

// Java code
LinuxFPFactory.dp_device_event event = new LinuxFPFactory.dp_device_event();
Pointer pEvent = new Pointer(event);
Function DPFPGetEvent = dpfpapi.getFunction("DPFPGetEvent");
DPFPGetEvent.invoke(res, pIdDev, new Pointer(pEvent), new Int(8000L)); //<- pEvent gets passed in here first
 
Pointer qImg = new Pointer(new Int(0));
Pointer qFtr = new Pointer(new Int(0));
 
Int ret = new Int();
Int nMinLen = new Int(0);
Int nLen = new Int(0);
Function FX_getFeaturesLen = dpFtrEx.getFunction("FX_getFeaturesLen");
FX_getFeaturesLen.invoke(ret, new Int(0), new Pointer(nLen), new Pointer(nMinLen));
if (ret.getValue() == 0)
{
    PrimitiveArray features = new PrimitiveArray(Int8.class, (int) nLen.getValue());
    Pointer pFeatures = new Pointer(features);
 
    Function FX_extractFeatures = dpFtrEx.getFunction("FX_extractFeatures");
    Int created = new Int(0);
    Parameter[] params = new Parameter[]{hFxContext, event.uDataSize, event.Data, new Int(0),
        nLen, pFeatures, qImg, qFtr, new Pointer(created)};
    FX_extractFeatures.invoke(ret, params); //<- this returns a failed error code
}
 
protected static final class DP_UID extends Structure
{
    public UInt32 uData1 = new UInt32(0);
    public UInt16 usData2 = new UInt16(0);
    public UInt16 usData3 = new UInt16(0);
    public PrimitiveArray ubData4 = new PrimitiveArray(UInt8.class, 8);
    public DP_UID()
    {
        init(new Parameter[]{uData1, usData2, usData3, ubData4});
        for (int i = 0, n = ubData4.getElementCount(); i < n; i++)
        {
            ubData4.setElement(i, new UInt8((short) 0));
        }
    }
}
 
protected static final class dp_device_event extends Structure
{
    public UInt nEvent = new UInt(0);
    public LinuxFPFactory.DP_UID deviceUid = new LinuxFPFactory.DP_UID();
    public UInt uDataSize = new UInt(0);
    public PrimitiveArray Data = new PrimitiveArray(Int8.class, 1);
    public dp_device_event()
    {
        init(new Parameter[]{nEvent, deviceUid, uDataSize, Data});
    }
}
 
Roman Kazmin TeamDev Ltd. 145 posts since
Nov 21, 2008
Currently Being Moderated
1. Oct 14, 2009 2:15 PM in response to: Monty Charlton
Re: Resized ‘struct’ on the heap

Hello Monty,

 

Thank you for letting us know that you have a problem with using of our product.

 

Your request has been registered in our tracking system with SPRT-54205 ID and set into the queue of issues that waiting for resolution.

We will get back to you as soon as we have any result.

 

Thank you for your patience and understanding in this matter.

 

Sincerely,

Roman



Serge Piletsky TeamDev Ltd. 997 posts since
Apr 24, 2006
Currently Being Moderated
2. Oct 16, 2009 5:26 PM in response to: Monty Charlton
Re: Resized ‘struct’ on the heap

Hi Monty,

 

I am sorry for the delay in responding to you.

 

In order to implement the Java wrapper for such type you need to consider two possible use cases. First is when the structure is created and initialized on a Java side and second one is when this structure is populated on a native side and then it returned back to Java application.

 

In first case you should know a number of elements in array, so we can use PrimitiveArray type. And in second case, when the number of elements in array is not known we should use ExternalArrayPointer to PrimitiveArray.

 

The example below demonstrates how to implement both these approaches in one structure class:

public class dp_device_event extends Structure {
    private UInt nEvent = new UInt();
    private LinuxFPFactory.DP_UID deviceUid = new LinuxFPFactory.DP_UID();
    private UInt uDataSize = new UInt();
    private PrimitiveArray Data;
    private ExternalArrayPointer DataPtr;
 
    // Creates structure
    public dp_device_event() {
        Data = new PrimitiveArray(Int8.class, 0);
        DataPtr = new ExternalArrayPointer(Data);
        init(new Parameter[]{
        nEvent,
        deviceUid,
        uDataSize,
        DataPtr});
    }
 
    // Creates and initializes structure
    public dp_device_event(Int8 data[]) {
        Data = new PrimitiveArray(data);
        DataPtr = null; // do not use external array pointer at all
        uDataSize.setValue(data.length);
        init(new Parameter[]{
        nEvent,
        deviceUid,
        uDataSize,
        Data});
    }
 
    public Int8[] getData() {
        // external array pointer is not initialized, read data directly from 'Data' array
        if (DataPtr == null) {
            return readElements(getDataSize());
        }
 
        // external array pointer is NULL
        if (DataPtr.isNull()) {
            return null;
        } else { 
            int numberOfElements = getDataSize();
            DataPtr.readArray(numberOfElements);
 
            return readElements(numberOfElements);
        }
    }
 
    private Int8[] readElements(int numberOfElements) {
        Int8 result[] = new Int8[numberOfElements];
        for (int i = 0; i < numberOfElements; i++) {
            result[i] = (Int8) Data.getElement(i);
        }
        return result;
    }
 
    public int getDataSize() {
        return (int) uDataSize.getValue();
    }
}

 

Please try this solution and let me know if you have any further questions.

 

-Serge

Serge Piletsky TeamDev Ltd. 997 posts since
Apr 24, 2006
Currently Being Moderated
4. Nov 2, 2009 5:26 PM in response to: Monty Charlton
Re: Resized ‘struct’ on the heap

Hi Monty,

 

Thank you for the update on this issue.

 

From the attached log file I see that the code tries to read the data from incorrect memory address. The possible cause of this error could be an incorect alingment of the structure. Therefore, please make sure that the alignment of dp_device_event structure is the same as in a corresponding C structure. You ca specify a required alignment in the init() method of the structure, for instance:

    public dp_device_event() {
        Data = new PrimitiveArray(Int8.class, 0);
        DataPtr = new ExternalArrayPointer(Data);
        init(new Parameter[]{
        nEvent,
         deviceUid,
        uDataSize,
        DataPtr}, (short) 8);
    }

To verify that a structure wrapper and particulary its alignment is correct you can use the getLength() method of a structure type that should return value which is equal to the sizeof(<Type>) on a native side.

 

-Serge

More Like This

  • Retrieving data ...