admin管理员组文章数量:1335854
This follows on from my earlier question. I now need to access a C++ struct that has multiple members of type std::vector<double>
or std::vector<int>
. However while I seem to successfully access the first member, the second produces garbage. Code below:
my_struct.cpp:
#include <iostream>
#include <memory>
#include <vector>
struct MyStruct {
int intVectorSize;
int doubleVectorSize;
std::vector<int> intVector;
std::vector<double> doubleVector;
};
extern "C" {
MyStruct* create_my_struct() {
MyStruct* myStruct = new MyStruct();
myStruct->intVectorSize = 2;
myStruct->doubleVectorSize = 2;
myStruct->intVector.push_back(5);
myStruct->intVector.push_back(6);
myStruct->doubleVector.push_back(1.1);
myStruct->doubleVector.push_back(2.3);
return myStruct;
}
void delete_my_struct(MyStruct* myStruct) {
delete myStruct;
}
}
BasicStruct.java
:
import com.sun.jna.Structure;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.util.Arrays;
import com.sun.jna.Library;
import com.sun.jna.Structure.FieldOrder;
public class BasicStruct {
public interface MyCppLibrary extends Library {
MyCppLibrary INSTANCE = (MyCppLibrary) Native.load("mycpp", MyCppLibrary.class);
@FieldOrder({"intVectorSize", "doubleVectorSize", "intVector", "doubleVector"})
public class MyStruct extends Structure {
public int intVectorSize;
public int doubleVectorSize;
public Pointer intVector;
public Pointer doubleVector;
}
MyStruct create_my_struct();
void delete_my_struct(MyStruct struct);
}
public static void main(String[] args) {
MyCppLibrary lib = MyCppLibrary.INSTANCE;
MyCppLibrary.MyStruct myStruct = lib.create_my_struct();
System.out.println("intVectorSize: " + myStruct.intVectorSize);
System.out.println("doubleVectorSize: " + myStruct.doubleVectorSize);
System.out.println("intVector: " + myStruct.intVector);
System.out.println("doubleVector: " + myStruct.doubleVector);
int[] intArray = myStruct.intVector.getIntArray(0, myStruct.intVectorSize);
double[] doubleArray = myStruct.doubleVector.getDoubleArray(0, myStruct.doubleVectorSize);
System.out.println("intVector contents: " + Arrays.toString(intArray));
System.out.println("doubleVector contents: " + Arrays.toString(doubleArray));
lib.delete_my_struct(myStruct);
}
}
Compiling the cpp code using g++
in WSL2 running Ubuntu 20.04 into a shared lib whose name matches that to be loaded from the Java code:
g++ -v -shared -fPIC -o libmycpp.so my_struct.cpp
And compiling and executing the Java code (ensuring that the JNA jar file is on the classpath):
$ javac -classpath ./jars/jna-5.15.0.jar BasicStruct.java
$ java -classpath ./jars/jna-5.15.0.jar:. BasicStruct
I get the following results:
intVectorSize: 2
doubleVectorSize: 2
intVector: native@0x7f0ea8294600
doubleVector: native@0x7f0ea8294608
intVector contents: [5, 6]
doubleVector contents: [6.9469400861921E-310, 0.0]
Note that while the output for the intVector
is correct, the output for the doubleVector
attribute shown is wrong.
I tried other combinations of ordering the attributes and notice after the first vector is read, the subsequent attributes appear corrupted.
Any suggestions on how to fix this? Thanks in advance.
This follows on from my earlier question. I now need to access a C++ struct that has multiple members of type std::vector<double>
or std::vector<int>
. However while I seem to successfully access the first member, the second produces garbage. Code below:
my_struct.cpp:
#include <iostream>
#include <memory>
#include <vector>
struct MyStruct {
int intVectorSize;
int doubleVectorSize;
std::vector<int> intVector;
std::vector<double> doubleVector;
};
extern "C" {
MyStruct* create_my_struct() {
MyStruct* myStruct = new MyStruct();
myStruct->intVectorSize = 2;
myStruct->doubleVectorSize = 2;
myStruct->intVector.push_back(5);
myStruct->intVector.push_back(6);
myStruct->doubleVector.push_back(1.1);
myStruct->doubleVector.push_back(2.3);
return myStruct;
}
void delete_my_struct(MyStruct* myStruct) {
delete myStruct;
}
}
BasicStruct.java
:
import com.sun.jna.Structure;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.util.Arrays;
import com.sun.jna.Library;
import com.sun.jna.Structure.FieldOrder;
public class BasicStruct {
public interface MyCppLibrary extends Library {
MyCppLibrary INSTANCE = (MyCppLibrary) Native.load("mycpp", MyCppLibrary.class);
@FieldOrder({"intVectorSize", "doubleVectorSize", "intVector", "doubleVector"})
public class MyStruct extends Structure {
public int intVectorSize;
public int doubleVectorSize;
public Pointer intVector;
public Pointer doubleVector;
}
MyStruct create_my_struct();
void delete_my_struct(MyStruct struct);
}
public static void main(String[] args) {
MyCppLibrary lib = MyCppLibrary.INSTANCE;
MyCppLibrary.MyStruct myStruct = lib.create_my_struct();
System.out.println("intVectorSize: " + myStruct.intVectorSize);
System.out.println("doubleVectorSize: " + myStruct.doubleVectorSize);
System.out.println("intVector: " + myStruct.intVector);
System.out.println("doubleVector: " + myStruct.doubleVector);
int[] intArray = myStruct.intVector.getIntArray(0, myStruct.intVectorSize);
double[] doubleArray = myStruct.doubleVector.getDoubleArray(0, myStruct.doubleVectorSize);
System.out.println("intVector contents: " + Arrays.toString(intArray));
System.out.println("doubleVector contents: " + Arrays.toString(doubleArray));
lib.delete_my_struct(myStruct);
}
}
Compiling the cpp code using g++
in WSL2 running Ubuntu 20.04 into a shared lib whose name matches that to be loaded from the Java code:
g++ -v -shared -fPIC -o libmycpp.so my_struct.cpp
And compiling and executing the Java code (ensuring that the JNA jar file is on the classpath):
$ javac -classpath ./jars/jna-5.15.0.jar BasicStruct.java
$ java -classpath ./jars/jna-5.15.0.jar:. BasicStruct
I get the following results:
intVectorSize: 2
doubleVectorSize: 2
intVector: native@0x7f0ea8294600
doubleVector: native@0x7f0ea8294608
intVector contents: [5, 6]
doubleVector contents: [6.9469400861921E-310, 0.0]
Note that while the output for the intVector
is correct, the output for the doubleVector
attribute shown is wrong.
I tried other combinations of ordering the attributes and notice after the first vector is read, the subsequent attributes appear corrupted.
Any suggestions on how to fix this? Thanks in advance.
Share Improve this question edited Nov 19, 2024 at 22:56 H3007 asked Nov 19, 2024 at 21:19 H3007H3007 627 bronze badges 5 |1 Answer
Reset to default 2It seems that JNA needs to access the raw array and not the std::vector
itself in order to convert it into a java array (see this for getIntArray
and getDoubleArray
). It means that your C structure has to provide the result of std::vector::data.
So the C library would be for instance:
#include <vector>
#include <cstdint>
struct MyStruct
{
int intVectorSize;
int doubleVectorSize;
const int32_t* intVectorPtr;
const double* doubleVectorPtr;
std::vector<int32_t> intVector;
std::vector<double> doubleVector;
};
extern "C"
{
MyStruct* create_my_struct()
{
MyStruct* myStruct = new MyStruct();
myStruct->intVector.push_back(5);
myStruct->intVector.push_back(6);
myStruct->intVectorSize = myStruct->intVector.size();
myStruct->intVectorPtr = myStruct->intVector.data();
myStruct->doubleVector.push_back(1.1);
myStruct->doubleVector.push_back(2.3);
myStruct->doubleVectorSize = myStruct->doubleVector.size();
myStruct->doubleVectorPtr = myStruct->doubleVector.data();
return myStruct;
}
void delete_my_struct(MyStruct* myStruct)
{
delete myStruct;
}
}
and the java part:
import com.sun.jna.Structure;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.util.Arrays;
import com.sun.jna.Library;
import com.sun.jna.Structure.FieldOrder;
public class BasicStruct
{
public interface MyCppLibrary extends Library
{
MyCppLibrary INSTANCE = (MyCppLibrary) Native.load("mycpp", MyCppLibrary.class);
@FieldOrder({"intVectorSize", "doubleVectorSize", "intVectorPtr", "doubleVectorPtr"})
public class MyStruct extends Structure
{
public int intVectorSize;
public int doubleVectorSize;
public Pointer intVectorPtr;
public Pointer doubleVectorPtr;
}
MyStruct create_my_struct();
void delete_my_struct(MyStruct struct);
}
public static void main(String[] args)
{
MyCppLibrary lib = MyCppLibrary.INSTANCE;
MyCppLibrary.MyStruct myStruct = lib.create_my_struct();
int[] intArray = myStruct.intVectorPtr .getIntArray (0, myStruct.intVectorSize);
double[] doubleArray = myStruct.doubleVectorPtr.getDoubleArray(0, myStruct.doubleVectorSize);
System.out.println("intVector contents : " + Arrays.toString(intArray));
System.out.println("doubleVector contents: " + Arrays.toString(doubleArray));
lib.delete_my_struct(myStruct);
}
}
Possible output:
intVector contents : [5, 6]
doubleVector contents: [1.1, 2.3]
本文标签: Access a C struct with two vectors from Java using JNAStack Overflow
版权声明:本文标题:Access a C++ struct with two vectors from Java using JNA - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742397809a2467276.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
MyStruct
that accesses the vectors instead of trying to directly access them. I don't know jna (only jni), but at the very least, I would think thatvector::data()
is what you should be returning to thePointer
type. – PaulMcKenzie Commented Nov 19, 2024 at 21:34vector
implementation it sees fit. A typical implementation is that avector
instance consists of three pointers and a separately allocated array. The three pointers point to the start of the array, to the end of the actually used part of the array and to the end of the array. – Codo Commented Nov 19, 2024 at 22:11javac -classpath ./jars/jna-5.15.0.jar BasicStruct.java
– edrezen Commented Nov 19, 2024 at 22:51