gpt4 book ai didi

java - 为 C 结构使用自定义创建器和删除器

转载 作者:太空宇宙 更新时间:2023-11-03 23:24:28 25 4
gpt4 key购买 nike

我在C端

typedef struct {} C_String;
C_String* StringNew();
void StringFree(C_String* string);

在 Java 上我得到了这样的包装器类

public class String {
private long swigCPtr;
protected boolean swigCMemOwn;

protected String(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}

protected static long getCPtr(String obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}

protected void finalize() {
delete();
}

public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
JNI.delete_C_String(swigCPtr);
}
swigCPtr = 0;
}
}

public String() {
this(JNI.new_C_String(), true);
}

}

JNI.new_С_String 和 JNI.delete_С_String 是由 SWIG 生成的 native 方法,它们的工作很简单 - 分配 C_String通过 malloc并通过 free 删除它分别。在我的情况下,情况应该有所不同,因为 C_String是空结构,就像捷径一样,正确的方法应该由 StringNew 分配。其中有 malloc在引擎盖下并释放 StringFree .

我想使用适当的方法而不是 JNI.new_String , JNI.delete_String实现这一目标的最简单方法是什么?

最佳答案

假设您显示的 C 位于名为 test.h 的文件中,以下 SWIG 界面将执行您想要的操作:

%module test

%{
#include "test.h"
%}

%extend C_String {
C_String() {
return StringNew();
}
~C_String() {
StringFree($self);
}
}

%ignore StringNew;
%ignore StringFree;

%include "test.h"

这使用 %extendC_String 类型提供自定义构造函数和析构函数。这个构造函数/析构函数对分别调用了 C 函数 StringNewStringFree

在您的问题中,您要求在生成的 Java 代码中进行这些调用。我在上面编写它的方式使这些调用改为从 C 内部发生。这有两个主要好处:

  1. 它是语言中性的 - 无论您的目标语言是什么,相同的界面文件都同样有效。
  2. 它最大限度地减少了 native 代码和 Java(或任何其他目标)代码之间的调用。从性能的角度来看,这通常是一件好事,因为这些跨语言跳转往往是界面中成本最高的部分。

这个答案的其余部分主要只是作为学习点而不是推荐的解决方案。

如果您真的想要,您可以将其编写为 Java 并进行您要求的 JNI 调用。为此,您需要编写一些 typemaps ,您至少需要两个(未经测试的)可能类似于:

  1. java体:

    %typemap(javabody) C_String %{
    private long swigCPtr;
    protected boolean swigCMemOwn;

    protected $javaclassname(long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
    }

    public $javaclassname() {
    $javaclassname tmp = $imclassname.StringNew();
    swigCMemOwn = tmp.swigCMemoryOwn;
    swigCPtr = tmp.swigCPtr;
    tmp.swigCMemoryOwn = false;
    }

    protected static long getCPtr($javaclassname obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
    }
    %}
  2. javadestruct:

    %typemap(javabody) C_String %{
    public synchronized void delete() {
    if (swigCPtr != 0) {
    if (swigCMemOwn) {
    swigCMemOwn = false;
    $imclassname.StringFree(swigCPtr);
    }
    swigCPtr = 0;
    }
    }
    %}

但如前所述,这确实不是解决问题的最佳方法。 (如果您希望在继承情况下仍然发生这种情况,您还需要一个“javadestruct_derived”类型映射)

关于java - 为 C 结构使用自定义创建器和删除器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30477383/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com