在 Java 中使用C++函数

Use a C++ function in Java

本文关键字:C++ 函数 Java      更新时间:2023-10-16

我有一个C++项目,其中包含一些.cpp和.h文件。其中一个.cpp具有具有此签名的函数:



int** verts(int L, int W, int l, int w)我想在 Java 项目中使用此函数。是的,我可以用Java重写它,但这是一个非常非常清晰的函数。从 Java 调用这个函数(并获得整数矩阵(会很棒。

知道吗?
请注意,我是一名Java程序员,我非常菜鸟C++ :P

你可以编写一个包含这个函数的库,并用一个 JNI 包装器,但它不是微不足道的。 最重要的问题是int**真正代表什么,以及如何管理它们:是否和您必须如何删除它们,以及如何在 Java 中表示它们。只是猜测,我怀疑指针指向一个int*数组,每个都指向一个int数组;这是一个常见的用 C 表示二维数组(但不是我们所要的通常在C++中使用(。 至于是否以及如何删除它们,这个应由定义verts的库记录。 鉴于此,您首先必须在 Java 类中将函数声明为本机函数:

class Verts
{
    static {
        System.loadLibrary( "<i>libraryName</i>" );
    }
    private static Integer[] nativeVerts( int L, int W, int l, int w );
    public Integer[][] verts( int L, int W, int l, int w )
    {
        Integer[] tmp = nativeVerts( L, W, l, w );
        //  reshape tmp...
        return reshapedData;
    }
}

(我更喜欢返回一个扁平的单维数组,而不是比Integer[][]. 这将使C++更简单。

您需要做的是按照以下行编写一个函数:

#include "jni.h"
extern "C" JNIEXPORT jIntArray JNICALL Java_Verts_nativeVerts(
    JNIEnv* env,
    jclass,
    jint L,
    jint W,
    jint l,
    jint w)
{
    int** results = verts( L, W, l, w );
    std::vector<int> tmp;
    //  Fill tmp with the flattened results.
    //  Then do whatever you have to do to clean up the int**.
    jintArray jResults = env->newIntArray( tmp.size() );
    env->SetIntArrayRegion( jResults, 0, tmp.size(), &tmp[0] );
    return jResults;
}

除了上述内容还需要进行更多的错误检查。

最后,编译上述内容并将其链接到具有您指定名称的 dll 中Java 端的System.loadLibrary()函数。 并确保您的环境已设置为Java可以找到dll(通过$LD_LIBRARY_PATH (Unix( 或 %path% (Windows(,或者通过传递路径在 Java 命令行上-Djava.library.path=...的方法(。

您将

无法直接使用该函数(或者,如果这样做,您将遇到内存泄漏,因为Java无法知道如何释放verts分配和返回的内存(。 不过,您应该能够编写遵循 JNI 规则的简单包装器。

跨语言调用时,确实需要使用调用方提供的缓冲区。 对于此函数,包装器需要将结果复制到调用方提供的缓冲区,然后使用适当的 C++ 函数释放 verts 返回的内存。