如何在 JNA 中使用 C++ 对象

How to work with C++ objects in JNA

我正在尝试使用 JNA 从 Java 访问 C++ 库。为此,我围绕我需要的 C++ 方法编写了一个简单的包装器。但是,包装 C++ 对象、传递给 Java 并返回到 C++ 会导致在访问 C++ 中的对象时出现无效内存访问。关于为什么会发生这种情况的任何指示都会非常有帮助。

newencoder.h

Class Encoder {

public:
Encoder();
~Encoder();

template<class Type>
bool originalEncode(Type* input);

}

encoder_wrapper.h

typedef void* EncoderWrap;

    extern "C" {
    EncoderWrap newEncoder();

    const char* encode(EncoderWrap vcEncoder);
    }

encoder_wrapper.cpp

#include "encoder_wrapper.h"
#include "newencoder.h"

EncoderWrap newEncoder() {
    return reinterpret_cast<void*>(new Encoder());
}

const char* encode(EncoderWrap encoderObj) {
        std::string input;
        (reinterpret_cast<Encoder*>(encoderObj))->originalEncode(&input); //This is where the invalid memory access occurs. Commenting this line and returning a placeholder string does not throw any error.
        return input.c_str();
    }

JNA

private static class Encoder {

    public static native Pointer newEncoder();
    public static native String encode(Pointer encoderObj);

    static {
            Native.setProtected(true);
            Native.register("encoderlib");
    }

}

//Code that calls the native methods

Pointer encoderObj = Encoder.newEncoder(); //Does not fail
String result = Encoder.encode(encoderObj); //Results in Invalid Memory access

我尝试从 C++ 方法 newEncoder() 中调用 encode() 方法,结果按预期工作。只有当我收到在 java 中转换为 void* 的编码器对象并将其传递回 C++ 方法 enocode().

时,才会发生此内存错误

抱歉post在这里发表评论,我没有足够的代表在评论部分正确post。

我对 java JNA 的东西没有太多经验,但在 C++ 世界

extern "C" {}

用于使C++代码具有C链接。在 encoder_wrapper.h 中,您使用的是 std::string,这是一个纯 C++ 结构。您是否尝试删除外部 "C"?

正如 Vybz 所建议的,您的问题是将 C++ 与 JNA 混合使用。 JNA 不了解 C++ 结构,需要纯 C。

换句话说,您不能假设 Java 字符串与 std::string 相同。您不能在界面中使用 std::string。

我通过将 void* 包含在一个结构中并将该结构返回给 JNA 来解决这个问题。每次调用 newEncoder 时,都会创建一个结构实例,该实例将有一个新的编码器对象,该对象被转换为 void* 作为成员。

结构对象每次都传递给encode函数。此方法依次将 void* 转换回对象并调用 originalEncode 方法。