【问题标题】:C++'s out parameter object creation and JNAC++的out参数对象创建和JNA
【发布时间】:2011-03-02 15:18:49
【问题描述】:

免责声明:我几乎忽略了关于 C++ 的所有内容,所以我希望我在这里没有说愚蠢的话,如果我是,请随时纠正我。

作为一名 Java 开发人员,当我想创建一个新对象时,我使用构造函数方法,该方法将在内存中分配该对象并为我返回一个句柄,我会将这个句柄存储在一个变量中,我会像这样。

Foo o = new Foo();

但在 C++ 中,我已经明白,尽管有可能这样做

Foo createFoo(){
    Foo f;
    f.doSomething();
    return f;
}

// ...

Foo f = createFoo();

我也可以自己定义一个句柄,然后在它上面调用一个初始化器来分配内存和绑定句柄,像这样:

void initializeFoo(Foo **f){
    f.doSomething();
    return;
}

// ...

Foo f;
initializeFoo(&f);

所以我的问题是,当我们想在 Java 中通过 JNA 使用这些 C++ 方法时会发生什么?

假设我有以下 C++ 标头:

typedef struct Foo f;

Foo createFoo();
void initializeFoo(Foo **f);

由于我不知道 Foo 是什么,或者 Foo 结构包含什么,所以我将创建一个 JNA PointerType 来声明我的结构:

public class Foo extends PointerType{

    public Foo(Pointer address) {
        super(address);
    }
    public Foo() {
        super();
    }
}

使用 createFoo 方法也应该很简单:

public class TestFoo{
    static{
        System.loadLibrary("foolib");
    }

    public static void main(String[] args){
        FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);

        Foo f = lib.createFoo();
    }

对吗?

但我的问题是,如何使用 initializeFoo 函数???我想我必须创建一个指针并将其提供给函数,但是如何在 JNA 中创建一个非 NULL 指针?我尝试了以下代码,但结果是 EXCEPTION_ACCESS_VIOLATION。

public class TestFoo{
    static{
        System.loadLibrary("foolib");
    }

    public static void main(String[] args){
        FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);

        Foo f = new Foo();
        lib.initializeFoo(f); // EXCEPTION_ACCESS_VIOLATION
        lib.initializeFoo(f.getPointer()); // EXCEPTION_ACCESS_VIOLATION
    }

有什么想法吗?

谢谢!

【问题讨论】:

  • 您的 C++ 函数和方法是否被正确导出?
  • @AJG85:是的,它们是 API 的一部分。

标签: java c++ pointers java-native-interface jna


【解决方案1】:
Foo f;
initializeFoo(&f);

initializeFoo() 不像你说的那样为 f“分配内存并绑定句柄”。 Foo f; 创建 f 并将其分配到内存中。 initializeFoo() 可以做一些事情,比如为 f 的成员属性赋值等等,以及创建另一个 Foo 对象并将其赋值给 f,但它不会按照你说的做。

另一方面,

Foo *f;
f = new Foo();

声明一个 Foo 指针。 new 分配内存并创建一个 Foo 对象,并将内存位置分配给 f(您可以将指针视为包含地址的整数)。

我认为您想了解更多关于 C++ 和指针的信息,然后再继续。

【讨论】:

    【解决方案2】:

    由于我不知道 Foo 是什么,或者 Foo 结构包含什么,所以我将创建一个 JNA PointerType 来声明我的结构

    这使得无法为 Foo 分配内存,因为您必须知道需要分配多少内存。对于 c 结构,jna​​ 需要一个镜像结构的 java 类,或者如果您至少知道它的大小,您可以尝试使用 Memory 类,它有一个带有大小参数的 ctor。

    对于使用继承等 c++ 特性的 c++ 结构和类,这会失败,因为所需的内存和布局取决于编译器和启用的优化。

    【讨论】:

    • @josefx:所以如果我不知道 Foo 结构,我就无法将我的 intializeFoo(Foo **f) 方法与 JNA 一起使用?
    • @josefx:我会尝试为这个结构分配内存,但我无法知道它的大小,它是在专有 API 中定义的。我想我可以通过将它定义为指针来避免这个问题。
    • @nathanb 如果它是在专有 api 中定义的,那么这个 api 要么提供一个返回指针的方法,要么有一个定义 Foo 结构的头文件。
    • @nathanb 你可以尝试 com.sun.jna.ptr.PointerByReference 并调用 getValue() 来获取结果指针。
    • @nathanb 你检查过jna.java.net 上的文档吗,它显示了PointerByReference 的示例。此外,您还可以传递一个 sp_session 的单个元素数组和一个非空 sp_session 值来获得相同的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 2014-05-04
    • 2012-02-05
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多