Вызов JNA по ссылке (получение списка структур из кода C — вызов из java)

#java #c #pass-by-reference #jna

#java #c #передача по ссылке #jna

Вопрос:

Ниже приведены классы, которые я использую в своем приложении для извлечения значений в качестве ссылки из библиотеки C.

 public class ShingleCoOrdJNAList extends Structure {
    
    public static class ByValue extends ShingleCoOrdJNAList implements Structure.ByValue {}
    public static class ByReference extends ShingleCoOrdJNAList implements Structure.ByReference {}
    
    public ByReference size;
    public ShingleCoOrdJNA.ByReference shingleCoords;
    
    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[] { "size","shingleCoords"});
    }

}

public class ShingleCoOrdJNA extends Structure {

    public static class ByReference extends ShingleCoOrdJNA implements Structure.ByReference {}
    public static class ByValue extends ShingleCoOrdJNA implements Structure.ByValue {}
    public Point.ByValue ShiP1;
    public Point.ByValue ShiP2;
    public Point.ByValue ShiP3;
    public Point.ByValue ShiP4;
    public Point.ByReference vDamagePts;
    public boolean bIsGood;
    public float fDamagePercentage;
    
    public ShingleCoOrdJNA()
    {
        this.bIsGood = true;
        this.fDamagePercentage = 0;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[] { "ShiP1","ShiP2","ShiP3","ShiP4","vDamagePts","bIsGood","fDamagePercentage"});
    }
}

public class Point extends Structure {

    public static class ByValue extends Point implements Structure.ByValue { }
    public static class ByReference extends Point implements Structure.ByReference { }
    public double x;
    public double y;
    
    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[] { "x","y"});
    }
}
  

Я вызываю библиотеку C, как показано ниже, из java

 ShingleCoOrdJNAList.ByReference shingleCoordList = new ShingleCoOrdJNAList.ByReference();
        
IntByReference size = new IntByReference();
                TestImgProcInterface.INSTANCE.callPerformShingleDetection(newMat.getNativeObjAddr(), pointList, 4, shingleCoordList, size, false, true);
  

Ниже приведен код C

 extern "C" void callPerformShingleDetection(Mat amp;FrameMat, struct PointListJNA pointList, int pointSize, struct ShingleCoOrdJNAList amp;damagePts, int amp;damagePtsSize, bool bShowResult, bool bDoDamageAnalysis) {
    vector<cv::Point> vPolyList;
    Point pXY;
    for(int i=0;i<pointSize;i  ) {
        pXY.x = pointList.points[i].x;
        pXY.y = pointList.points[i].y;
        vPolyList.push_back(pXY);
    }
    vector<ShingleCoOrd> vShingleList;
    PerformShingleDetection(FrameMat, vPolyList, vShingleList, bShowResult, bDoDamageAnalysis);
    std::cout << "Image processing completed" << endl;

    damagePts = {};
    damagePts.size = vShingleList.size();
    damagePts.shingleCoords = (ShingleCoOrdJNA*)malloc(sizeof(ShingleCoOrdJNA) * vShingleList.size());
    for(int j=0;j<vShingleList.size();j  ) {
        damagePts.shingleCoords[j].ShiP1 = getJNAPoint(vShingleList[j].ShiP1);
        damagePts.shingleCoords[j].ShiP2 = getJNAPoint(vShingleList[j].ShiP2);
        damagePts.shingleCoords[j].ShiP3 = getJNAPoint(vShingleList[j].ShiP3);
        damagePts.shingleCoords[j].ShiP4 = getJNAPoint(vShingleList[j].ShiP4);
        damagePts.shingleCoords[j].bIsGood = vShingleList[j].bIsGood;
        damagePts.shingleCoords[j].fDamagePercentage = vShingleList[j].fDamagePercentage;
        damagePts.shingleCoords[j].vDamagePts = (Points*)malloc(sizeof(Points) * vShingleList[j].vDamagePts.size());
        for(int m=0;m<vShingleList[j].vDamagePts.size();m  ) {
            damagePts.shingleCoords[j].vDamagePts[m] = getJNAPoint(vShingleList[j].vDamagePts[m]);
        }
        std::cout << "vShingleList[j].vDamagePts.size()" << vShingleList[j].vDamagePts.size() << endl;
    }
    std::cout << "Size of shingle detected" << vShingleList.size() << endl;
}
  

Я получаю сообщение об ошибке, как показано ниже.

 #
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f45cdbfd6a7, pid=11278, tid=0x00007f46340a9700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [jna7588690608297773974.tmp 0x96a7]  Java_com_sun_jna_Native__1getPointer 0xc7
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/user1/workspace/ImageProcessor/hs_err_pid11278.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
  

Я могу печатать все выполнения в классе C. Но не могу вернуть данные в моем классе Java. Единственная проблема заключается в том, когда я передаю vDamagePts в моем классе C. В остальном все работает нормально.

Комментарии:

1. Какое значение vShingleList[j].vDamagePts.size() перед выделением damagePts.shingleCoords[j].vDamagePts , поскольку оно еще не создано?

2. @ecle : это значение мы получаем из другой библиотеки. Мы правильно получаем значение из этой библиотеки.

3. Пожалуйста, включите также объявления структур C. Обратите внимание на этот момент. ByValue является излишним в качестве поля структуры; семантика по значению является значением по умолчанию в этом контексте.