jna,c++接口映射

研究了两天,读了好些博客,终于把问题解决了

问题是:c++库里有这样的复杂结构体,以及处理

//c.h

//点
typedef struct{
    int x;
    int y;
}POINT;
//轮廓
typedef struct{
    int num_of_points;    //点数
    POINT *pPoint;        //POINT数组指针
}CONTOUR;
//轮廓集合
typedef struct{
    int num_of_contours;    //轮廓数
    CONTOUR *pContour;      //CONTOUR数组指针
}POLYGON;

extern "C" __declspec(dllexport)
void process_polygon(POLYGON &polygon){
    polygon.num_of_contours=getNumOfContours();//伪码,意为此数为变数
    polygon.pContour=new CONTOUR[polygon.num_of_contours];//动态开辟
    for(int i=0;i<polygon.num_of_contours;++i){
        polygon.pContour[i].num_of_points=getNumOfPoints(i);//伪码,意为此数为变数
        polygon.pContour[i].pPoint=new POINT[polygon.pContour[i].num_of_points];//动态开辟
    }    
}

我要从java里映射这样的结构体,可以使用jna的Pointer直接映射结构体里的指针,因为传的POLYGON是引用,所以在c++库里给指针新赋的值(开的空间),在java里是可以获取到的(同一个内存空间)。Java里映射如下

//Proc.java
//点
public class POINT extends Structure{
    public int x;
    public int y;
    //用构造函数反解出结构体,Pointer.getXXX(int offset)
    public POINT(Pointer p,int offset){
        x=p.getInt(offset);
        offset+=8;
        y=p.getInt(offset);
    }
    public POINT(){}
    @override
    protected List getFieldOrder(){return Arrays.asList("x","y");}
    public class ByReference extends POINT implements Structure.ByReference{}
    public class ByValue extends POINT implements Structure.ByValue{}
}
//轮廓
public class CONTOUR extends Structure{
    public int num_of_points;
    public Pointer pPoint=new Pointer(0);//使用指针
    //用构造函数反解出结构体,Pointer.getXXX(int offset)
    public CONTOUR(Pointer p,int offset){
        num_of_points=p.getInt(offset);
        offset+=8;
        pPoint=p.getPointer(offset);
    }
    public CONTOUR(){}
    @override
    protected List getFieldOrder(){return Arrays.asList("num_of_points","pPoint");}
    public class ByReference extends CONTOUR implements Structure.ByReference{}
    public class ByValue extends CONTOUR implements Structure.ByValue{}
}
//轮廓集合
public class POLYGON extends Structure{
    public int num_of_contours;
    public Pointer pContour=new Pointer(0);
    //用构造函数反解出结构体,Pointer.getXXX(int offset)
    public POLYGON(Pointer p,int offset){
        num_of_contours=p.getInt(offset);
        offset+=8;
        pContour=p.getPointer(offset);
    }
    public POLYGON(){}
    @override
    protected List getFieldOrder(){return Arrays.asList("num_of_contours","pContour");}
    public class ByReference extends POLYGON implements Structure.ByReference{}
    public class ByValue extends POLYGON implements Structure.ByValue{}
}
//用POLYGON.ByReference将polygon以引用的方式传到c库
void process_polygon(POLYGON.ByReference polygon);

c库处理完后,java里从指针处拿数据,如下

//c库处理完后,用CONTOUR[] contours,POINT[][] points来存数据
public void test(){
    POLYGON.ByReference polygon=new POLYGON.ByReference();
    process_polygon(polygon);
    CONTOUR[] contours=new COUNTOUR[polygon.num_of_contours];
    POINT[][] points=new POINT[polygon.num_of_contours][];
    for(int i=0;i<polygon.num_of_contours;++i){
        contours[i]=new CONTOUR(polygon.pContour,i*16);//每个结构体占16字节
        points[i]=new POINT[contours[i].num_of_points];
        for(int j=0;j<contours[i].num_of_points;++j)
            points[i][j]=new POINT(coutours[i].pPoint,j*16);//每个结构体占16字节
    }
}

此外,c中函数参数若为指针的话,在函数中对指针赋新值,如下

void proc_ptr(int *p){
    int a=8;
    p=&a;
}

将不会改变传入指针所指向的内容,原因也很简单,参数传递是传指针的值而非指针的引用,若要改变指针指向的内容,就需要改变原指针,那就要传指针的引用,如下

void proc_ptr(int *&p){
    int a=8;
    p=&a;
}

如此可达到目的。

我又发现了更简单的方法,不用自己去解析结构体,我当初就是这样觉得,只是没找到具体怎么实现,应该这样做,java里把指针都定义为对应结构体的ByReference,然后用这个ByReference的toArray(int size)直接转成对象数组就ok了

//Proc.java
//点
public class POINT extends Structure{
    public int x;
    public int y;
    @override
    protected List getFieldOrder(){return Arrays.asList("x","y");}
    public class ByReference extends POINT implements Structure.ByReference{}
    public class ByValue extends POINT implements Structure.ByValue{}
}
//轮廓
public class CONTOUR extends Structure{
    public int num_of_points;
    public POINT.ByReference pPoint=new POINT.ByReference();//使用指针
    @override
    protected List getFieldOrder(){return Arrays.asList("num_of_points","pPoint");}
    public class ByReference extends CONTOUR implements Structure.ByReference{}
    public class ByValue extends CONTOUR implements Structure.ByValue{}
}
//轮廓集合
public class POLYGON extends Structure{
    public int num_of_contours;
    public CONTOUR.ByReference pContour=new CONTOUR.ByReference();
    @override
    protected List getFieldOrder(){return Arrays.asList("num_of_contours","pContour");}
    public class ByReference extends POLYGON implements Structure.ByReference{}
    public class ByValue extends POLYGON implements Structure.ByValue{}
}
//用POLYGON.ByReference将polygon以引用的方式传到c库
void process_polygon(POLYGON.ByReference polygon);

这样就好了,polygon在c库中处理完后,这样得到数据

//c库处理完后,用CONTOUR[] contours,POINT[][] points来存数据
public void test(){
    POLYGON.ByReference polygon=new POLYGON.ByReference();
    process_polygon(polygon);
    CONTOUR[] contours=(CONTOUR[])polygon.pContour.toArray(polygon.num_of_contours);
    POINT[][] points=new POINT[polygon.num_of_contours][];
    for(int i=0;i<polygon.num_of_contours;++i){
        points[i]=(POINT[])contours[i].pPoints.toArray(contours[i].num_of_points);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值