0

我有一个本地 C 结构,其中包含一个指向字符串的指针:

struct mystruct {
  char *name;
}

以及为名称分配内存的本机函数:

void fill(struct mystruct *s, int count) {
  for (int i = 0; i < count; i++)
    s[i].name = strdup("something");
}

对应的Java结构和native方法是

class MyStruct extends Structure {
  String name;
}

void fill(MyStruct[] structs, int count)用于填充一些实例。然后我会这样使用它:

MyStruct[] structs = new MyStruct[10];
fill(structs, structs.length);

完成后,必须调用一个清理例程void free(MyStruct[] structs),它清理整个数组(所有由 strdup 分配的内存)。没有办法对 struct instance-by-instance 方法进行清理。

我面临的问题是释放数组后,Java 字符串已损坏。如何为每个 MyStruct 实例创建一个副本,以便我可以释放本机内存,并且只处理使用纯 Java 字符串的 MyStruct 实例?

4

2 回答 2

1

一旦释放了struct支持 .

如果您需要手动管理内存,请不要将该字段映射到 aString而是使用Pointer,例如

class MyStruct extends Structure {
    public Pointer name;
    public String getName() { return name == null ? null : name.getString(0); }
}

一般来说,在释放其本机内存支持后使用 JNA不会直接受到伤害Structure,只要您不调用Structure.read()or Structure.write()(请注意,JNA 在本机函数调用之前和之后自动调用这些方法)。但是,如果您选择这样做,请确保您知道自己在做什么;有更安全的方法来开发您的代码。

于 2013-08-21T11:40:02.083 回答
0

虽然 MyStruct 没有实现Cloneable接口,但它有一个clone()方法继承自java.lang.Object. 因此,我相信,您可以clone()在不干扰 JNA 的情况下进行覆盖。

class MyStruct {
    String name;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        MyStruct myStruct = new MyStruct();
        myStruct.name = new String(this.name);
        return myStruct;
    }
}

您现在可以迭代structs和克隆每个元素。如果由于扩展而这不起作用Structure,您可以更改上述方法,以便实例化一个不同的(非本机)类。

class MyStruct {
    String name;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new NonNativeStruct(new String(name));
    }
}

class NonNativeStruct {
    private String name;
    public NonNativeStruct(String name) {
        this.name = name;
    }
}

请注意,您违反了x.clone().getClass() == x.getClass()这样做的合同。

于 2013-08-20T22:57:08.547 回答