我有这个C++结构和方法,它在.dll/.so中返回:
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
emxArray_real_T *emxCreate_real_T(int rows, int cols)
{
emxArray_real_T *emx;
***
return emx;
}
我试着从Java通过南国防军给它打电话。我的目标是在Java接收这个结构“emxarray_real_t”,以获得对其字段的访问权。我从一个非常简单的代码开始,并以此结束,但仍然有问题--我收到了错误的数据在“大小”,“数据”等。
public interface TestJna extends Library {
TestJna INSTANCE = (TestJna)Native.load(Platform.isWindows() ? "some.dll" : "some.so", TestJna.class);
@Structure.FieldOrder({"allocatedSize","canFreeData","data", "numDimensions", "size"})
public static class ContentsJna extends Structure {
public ContentsJna() {
}
public int allocatedSize;
public boolean canFreeData;
private Pointer bufferData;
private Pointer bufferSize;
public Pointer data = new Memory(Double.SIZE);
public int numDimensions;
public Pointer size = new Memory(Integer.SIZE);
public double[] getData() {
Pointer p = data.getPointer(0);
if (p == null) return null;
return p.getDoubleArray(0, allocatedSize);
}
public void setData(double[] data) {
Pointer p = this.data.getPointer(0);
if (p == null) {
p = bufferData = new Memory(data.length * 8);
this.data.setPointer(0, bufferData);
}
p.write(0, data, 0, data.length);
}
public int[] getSize() {
Pointer p = data.getPointer(0);
if (p == null) return null;
return p.getIntArray(0, allocatedSize);
}
public void setSize(int[] size) {
Pointer p = this.size.getPointer(0);
if (p == null) {
p = bufferSize = new Memory(size.length * 4);
this.size.setPointer(0, bufferSize);
}
p.write(0, size, 0, size.length);
}
}
ContentsJna emxCreate_real_T(int rows, int cols);
}
我该怎么修好它?我遵循了这一指南,但它并没有帮助我完全解决问题:JNA本机html" target="_blank">函数调用和具有双指针/数组内存分配的结构
UPD16.02/21:@Matthias Bläsing,谢谢你这个伟大的解决方案--它帮助我认识到了自己的错误。与C++输出相比,我有一些错误的数据输出。也许我应该提供完整的C++代码:
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
emxArray_real_T *emxCreate_real_T(int rows, int cols)
{
emxArray_real_T *emx;
int numEl;
emxInit_real_T(&emx, 2);
emx->size[0] = rows;
numEl = rows * cols;
emx->size[1] = cols;
emx->data = (double *)calloc((unsigned int)numEl, sizeof(double));
emx->numDimensions = 2;
emx->allocatedSize = numEl;
return emx;
}
void emxInit_real_T(emxArray_real_T **pEmxArray, int numDimensions)
{
emxArray_real_T *emxArray;
int i;
*pEmxArray = (emxArray_real_T *)malloc(sizeof(emxArray_real_T));
emxArray = *pEmxArray;
emxArray->data = (double *)NULL;
emxArray->numDimensions = numDimensions;
emxArray->size = (int *)malloc(sizeof(int) * numDimensions);
emxArray->allocatedSize = 0;
emxArray->canFreeData = true;
for (i = 0; i < numDimensions; i++) {
emxArray->size[i] = 0;
}
}
c++和Java的比较输出与参数:emxcreate_real_t(1024,12)
此处的调用的比较输出:emxcreate_real_t(1024,12)
C++(正确):
=============
[0]:
data: 0.0
size: 1024
allocatedSize: 12288
numDimensions: 2
canFreeData: True
=============
[1]:
data: 0.0
size: 12
allocatedSize: 12288
numDimensions: 2
canFreeData: True
=============
[2]:
data: 0.0
size: 0
allocatedSize: 12288
numDimensions: 2
canFreeData: True
=============
Java(不正确):
=============
[0]:
data: 6.9475440396446E-310
size: -1672347344
allocatedSize: 32740
numDimensions: 12288
canFreeData: true
=============
[1]:
data: 6.94754379426234E-310
size: 32740
allocatedSize: 32740
numDimensions: 12288
canFreeData: true
=============
[2]:
data: 4.243997653E-314
size: 12288
allocatedSize: 32740
numDimensions: 12288
canFreeData: true
=============
我认为问题在于分配规模的差异如下:
emx->data = (double *)calloc((unsigned int)numEl, sizeof(double));
但不知道如何解决它--使用字节和UnsignedInt的转换对我没有帮助。:(
UPD:20.02.21:@Matthias Bläsing再次感谢你的帮助。如何将Getters和Setters写入这个新结构,其中包含指向工作结构“emxarray_real_t”的指针(“this Pointer”*emxdata“”)C++结构代码:
typedef struct {
emxArray_real_T *emxData;
double timeStamp;
} struct0T;
Java结构代码:
@Structure.FieldOrder({"emxData","timeStamp"})
public class Struct0T extends Structure {
public Pointer emxData;
public double timeStamp;
public emxArray_real_T getEmxData() {
if (emxData == null) {
throw new IllegalArgumentException("emxData is null");
}
// ???
return ???;
}
public void setData(emxArray_real_T emxArray) {
if (emxData == null ) {
throw new IllegalArgumentException("emxData is null");
}
final Pointer pointer = emxArray.getPointer(); // Or re-calculate Pointer by multiplying arrays size on Double/Integer sizes etc here for all fields?
if(pointer == null) {
throw new IllegalArgumentException("pointer is null");
}
this.emxData = pointer;
}
}
Jna库中的代码:
public interface TestJna extends Library {
***
void calculation(emxArray_real_T input_str, emxArray_real_T output_str);
}
UPD 11.03.21:double[]<->byte[]转换(试图解决Linux问题):
getData()setData中的更改:
public double[] getData() {
final int times = Double.SIZE / Byte.SIZE;
if (data == null) {
return new double[0];
}
return ByteDoubleConverterUtils.toDoubleArray(data.getByteArray(0, allocatedSize * times));
}
public void setData(double[] data) {
final byte[] bytes = ByteDoubleConverterUtils.toByteArray(data);
this.data.write(0, bytes, 0, bytes.length);
}
实用工具类:
public class ByteDoubleConverterUtils {
public static byte[] toByteArray(double[] doubleArray){
int times = Double.SIZE / Byte.SIZE;
byte[] bytes = new byte[doubleArray.length * times];
for(int i=0;i<doubleArray.length;i++){
final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes, i * times, times);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putDouble(doubleArray[i]);
}
return bytes;
}
public static double[] toDoubleArray(byte[] byteArray){
int times = Double.SIZE / Byte.SIZE;
double[] doubles = new double[byteArray.length / times];
for(int i=0;i<doubles.length;i++){
final ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray, i * times, times);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
doubles[i] = byteBuffer.getDouble();
}
return doubles;
}
}
主要问题是,@Structure.FieldOrder是错误的。您需要匹配本机字段顺序,以便运行库能够将正确的Java变量与正确的内存位置关联起来。在声明中,第一个成员是allocatedSize(Java站点),但在本机代码中,它是指向数据的指针。
@Structure.FieldOrder({"data", "size", "allocatedSize", "numDimensions", "canFreeData"})
public static class emxArray_real_T extends Structure {
public static class ByReference extends emxArray_real_T implements Structure.ByReference {
public ByReference() {
}
public ByReference(Pointer p) {
super(p);
}
}
public Pointer data;
public Pointer size;
public int allocatedSize = 1;
public int numDimensions = 1;
public boolean canFreeData = false;
public emxArray_real_T() {
}
public emxArray_real_T(Pointer p) {
super(p);
}
public double[] getData() {
if (data == null) {
return new double[0];
}
return data.getDoubleArray(0, allocatedSize);
}
public void setData(double[] data) {
if (data.length != allocatedSize) {
throw new IllegalArgumentException("Data must have a length of " + allocatedSize + " but was " + data.length);
}
this.data.write(0, data, 0, data.length);
}
public int[] getSize() {
if (size == null) {
return new int[0];
}
return size.getIntArray(0, numDimensions);
}
public void setSize(int[] size) {
if (size.length != numDimensions) {
throw new IllegalArgumentException("Size must have a length of " + numDimensions + " but was " + size.length);
}
this.size.write(0, size, 0, size.length);
}
}
当您使用它时,请检查boolean_T是否为32bit。如果是1byte,则映射到byte。
对于包含对emxarray_real_t
引用的结构,您需要一个实现标记接口com.sun.jna.Structure.byreference
的结构。具有该标记接口的结构通过引用传递,并且当嵌入到其他结构中时,指向这些结构的指针嵌入到父结构中,而不是子结构本身。
@Structure.FieldOrder({"emxData","timeStamp"})
public class Struct0T extends Structure {
public emxArray_real_T.ByReference emxData;
public double timeStamp;
}
要从Structure.ByReference转换为Structure.ByReference,可以运行(如果来自本机):
emxArray_real_T.ByReference t1ByReference = Structure.newInstance(emxArray_real_T.ByReference.class, input.getPointer());
t1ByReference.read();
如果结构是在Java端创建的,并且数据是由内存对象支持的,那么建议使用复制构造函数,以便保持引用不变。
我使用的是名为Gson的Google JSON API,在设置Java类以便使用方法时遇到了困难。 从JSON数据中,我知道有一个包含所有数据的对象数组。让我感到困惑的是外部标记。我知道我必须构造一个表示对象的类,但是我是否也必须创建一个表示的类,因为它包含? 目前,我有一个名为的文件,其中包含以下内容: 我只包括了我计划使用的变量。上面的JSON数据包含在一个名为的字符串中,这就是我在main方
这是我第一次使用JNA。我想做的是在一个DLL中调用一个函数 这是我的JNA结构“新设备” 我正在尝试使用“updateStrucureByReference(类类型、对象、对象指针)”更新字段。我不相信我的“类类型”参数是正确的还是正确的?我是不是做错了什么事?将非常感谢任何输入。 当我尝试打印字段时,它们似乎都是零。 在我的主要班级里
问题内容: 这个问题已经在这里有了答案 : 7年前关闭。 可能重复: 如何从文件内容创建Java字符串 我有一个HTML文件,我想用它来提取信息。为此,我正在使用Jsoup。现在使用Jsoup,我需要将html文件转换为字符串。我怎样才能做到这一点? 现在,我想要一个String对象,其中包含html文件中的内容。 问题答案: 我使用apache common IO将文本文件读取为单个字符串 简单
问题内容: 我对用Java转换对象的含义感到困惑。 说你有… 这是怎么回事 变量类型会更改吗,还是变量内的对象会更改?很迷茫。 问题答案: 看一下这个样本:
如何将hashmap转换或强制转换为Java中的JSON对象,并再次将JSON对象转换为JSON字符串?
最近,我开始使用OpenCSV的CSVReader将数据从CSV文件获取到java中的JTable,但我不断收到错误。DaTroop在这里给出了如何从CSV获取数据的答案:将CSV导入JTable 到Netbeans IDE 7.4,但我一直得到错误“不兼容的类型-对象无法转换为TableModel”。在……里 有什么想法吗? 谢谢 正如在评论中一样,请找到我的整个代码片段。JFrame可以工作和