【发布时间】:2020-02-03 10:18:00
【问题描述】:
在我当前的项目中,我必须在 java 项目中实现原生 c 库的功能。 我正在使用 JNA。并且到目前为止取得了一些不错的成绩。 现在我陷入了以下问题。
我必须调用原生 c 函数:
int retrieveResult(ResultStruct * pResult)
结构体的定义如下:
typedef struct tag_ResultStruct
{
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;
在 Java 中,我创建了一个代表结构的类:
public class ResultStruct extends Structure{
public Pointer pBuffer;
public int sizeX;
public int sizeY;
@Override
protected List<String> getFieldOrder(){
return Arrays.asList(new String[] {"pBuffer", "sizeX", "sizeY"});
}
public ResultStruct(){
}
}
我正在调用本机 C 方法
private interface MyCLib extends Library{
MyCLib INSTANCE = Native.load("myclib", MyCLib.class);
int retrieveResult(ResultStruct pResult);
}
ResultStruct resultStruct = new ResultStruct();
resultStruct.pBuffer = new Memory(bufferLen);
int res = MyCLib.INSTANCE.retrieveResult(resultStruct);
现在我可以从 sizeX、sizeY 和 pBuffer 中检索预期值了
resultStruct.pBuffer.getByteArray(0, bufferLen);
现在我像下面这样扩展我的结构:
typedef struct tag_ResultStruct
{
const void* pContext;
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;
还有我的 Java 结构:
public class ResultStruct extends Structure{
public Pointer pContext;
public Pointer pBuffer;
public int sizeX;
public int sizeY;
@Override
protected List<String> getFieldOrder(){
return Arrays.asList(new String[] {"pContext", "pBuffer", "sizeX", "sizeY"});
}
public ResultStruct(){
}
}
问题是,我不想使用 pContext。所以我不知道它应该有什么大小,因此我不初始化指针。 现在,当我尝试通过调用从缓冲区中检索值时:
resultStruct.pBuffer.getByteArray(0, bufferLen);
我没有从缓冲区中得到预期值。
问题
在使用JNA时,如何处理通过引用传递的结构内的多个动态内存字段? 可以在结构中保持未初始化的指针吗?
感谢任何帮助。提前谢谢你。
【问题讨论】:
-
这里有一组非常酷的基于 JNA 的示例:eshayne.com/jnaex
-
谢谢。我已经看过这些例子了。但是,当结构通过引用传递时,没有检索结构内部数组的示例。
-
你的 API 告诉你应该为上下文指针传递什么?在分配具有必要值的
Memory对象时应该非常相似。 -
请注意,结构填充可能在这里起作用。您的数据可能会发生对齐和读取不正确的情况。我建议玩
#pragma pack和setAlignType(ALIGN_NONE);。如果您无法访问(库的)源,最好使用JNI访问它,您可以更好地控制细节。您可以决定(在代码的本机部分内)您的数据将如何在C和Java之间精确映射。
标签: java c pointers struct jna