用qt将对象返回到指针jna

时间:2014-05-20 15:19:15

标签: java c++ qt jna

我正在研究JNA项目:

  • 有些文件是用JAVA编写的。
  • 其他的是用C ++(QT)编写的。
  • CPP文件正在链接JAVA和C ++。

JAVA项目使用JNA的3.0.9版本:
http://mvnrepository.com/artifact/com.sun.jna/jna/3.0.9

我在Windows 8上使用QT 5.2和JAVA 1.7。 我将qt dll从qt文件夹复制到我的JAVA项目,以便应用程序可以工作。 我不知道如何在JAVA方法中从属于dll的方法中获取返回的对象。我看到了有关Pointer的文档,但是我没有找到适合从dll中的已开发方法获取对象的类型。

我的qt项目文件:

#-------------------------------------------------
#
# Project created by QtCreator 2014-05-17T21:25:07
#
#-------------------------------------------------

QT       -= gui

TARGET = composite
TEMPLATE = lib

SOURCES += classes/my_component_class.cpp\
        classes/my_composite_class.cpp\
        wrapper.cpp

HEADERS += classes/my_component_class.h\
        classes/my_composite_class.h

类/ my_component_class.h:

#ifndef MY_COMPONENT_CLASS_H
#define MY_COMPONENT_CLASS_H

class MyComponentClass {

private:

    int myFirstField;
    int mySecondField;

public:
    MyComponentClass();
    MyComponentClass(int,int);
    void setMyFirstField(const int&);
    void setMySecondField(const int&);
    const int& getMyFirstField() const;
    const int& getMySecondField() const;
};

#endif

类/ my_component_class.cpp:

#include "classes/my_component_class.h"
MyComponentClass::MyComponentClass(){
    myFirstField = 0;
    mySecondField = 0;
}

MyComponentClass::MyComponentClass(int _myFirstField,int _mySecondField){
    setMyFirstField(_myFirstField);
    setMySecondField(_mySecondField);
}

void MyComponentClass::setMyFirstField(const int& _myFirstField) {
    myFirstField = _myFirstField;
}

void MyComponentClass::setMySecondField(const int& _mySecondField) {
    mySecondField = _mySecondField;
}

const int& MyComponentClass::getMyFirstField() const{
    return myFirstField;
}

const int& MyComponentClass::getMySecondField() const{
    return mySecondField;
}

类/ my_composite_class.h:

#ifndef MY_COMPOSITE_CLASS_H
#define MY_COMPOSITE_CLASS_H

#include <QList>
#include "classes/my_component_class.h"

class MyCompositeClass {

private:

    QList<MyComponentClass> list;

public:

    MyCompositeClass();
    void setList(const QList<MyComponentClass>&);
    const QList<MyComponentClass>& getList() const;
    QList<MyComponentClass>& refList();
};

#endif

类/ my_composite_class.cpp:

#include "classes/my_composite_class.h"
MyCompositeClass::MyCompositeClass() {
    list << MyComponentClass(1,2);//Some objects are added to the list
    list << MyComponentClass(3,4);
}
void MyCompositeClass::setList(const QList<MyComponentClass>& _list) {
    list = _list;
}

const QList<MyComponentClass>& MyCompositeClass::getList() const{
    return list;
}

QList<MyComponentClass>& MyCompositeClass::refList() {
    return list;
}

wrapper.cpp:

#include "classes/my_composite_class.h"

extern "C"{

    static MyCompositeClass* composite = NULL;

    void create(){
        if(composite == NULL) {//Create once
            composite = new MyCompositeClass();
        }
    }

    void* list() {
        create();//Avoid segmentation fault
        //Does it exist an other way to get pointer from the returned list?
        return &(composite->refList());
    }


    void destroy(){
        if(composite != NULL){
            //Delete the instance only if there is a created instance
            delete composite;
            composite = NULL;
        }
    }

}

我正在使用Windows 8,因此输出dll是composite.dll

IComposite.java:

package mainPackage;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface IComposite extends Library{

    //Load dll once
    public IComposite INSTANCE = (IComposite) Native.loadLibrary("composite", IComposite.class);

    //usable methods in the JAVA code
    public void create();
    public void destroy();
    public Pointer list();
}

CompositeSample.java:

package mainPackage;
public class CompositeSample{

    public static void main(String[] args) {
        String path_ = CompositeSample.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        if (path_.endsWith(".jar")) {
            //In order to treat executable jars, it is recommanded to change
            //the property of java.library.path
            System.setProperty("java.library.path", path_.substring(1)+"!/");
        }
        IComposite integerMath = IComposite.INSTANCE;
        integerMath.create();
        // What do I have to do with the returned pointer from the method "list" of the interface "IComposite"
        // in order to get the list from the returned pointer?
        integerMath.destroy();// free allocated memory
    }

}

感谢能够帮助我的人们。

2 个答案:

答案 0 :(得分:3)

我不是JNA的专业人士,所以这只是一个提示。 我认为不可能神奇地获取非基本类型指针中包含的值。在我看来,你应该在Java中为MyComponentClass创建一个映射类型。不幸的是我不知道怎么做。

如果我是你,我会以简单的方式做到;创建一个包含我的数据的结构,并使用此结构作为返回值,而不是返回整个类对象。

检查此示例以了解如何映射结构以及如何使用JNA发送/检索结构数组 http://www.eshayne.com/jnaex/example06.html

答案 1 :(得分:2)

开箱即用,Java对QList类型一无所知,因此您只能将其视为Java代码中的不透明指针。要解决此问题,您可以只公开普通的C API,也可以提供Java Qt包装器。

看看Qt Jambi。它是Qt的Java绑定,可以让你在Java中使用Qt类型。具体来说,Jambi generator将自动为您的C ++代码生成Java包装器,并自动在Qt集合和Java集合之间进行转换。