When I try to get the struct return value in C++, I cannot resolve the value in the struct.
This is my structure.
struct Point {
int x;
int y;
};
This is my C++ method
Point test_point(Point points[],long count)
{
if (count <= 0) {
// Return a default Point with x and y set to 0
Point defaultPoint = { 0, 0 };
return defaultPoint;
}
Point maxPoint = points[0];
int maxSum = maxPoint.x + maxPoint.y;
for (int i = 1; i < count; ++i) {
int currentSum = points[i].x + points[i].y;
if (currentSum > maxSum) {
maxSum = currentSum;
maxPoint = points[i];
}
}
int x = maxPoint.x;
int y = maxPoint.y;
std::cout << "x = " << x << ", y = " << y << std::endl;
return maxPoint;
}
This is my Java method
public static void dereferenceSegmentsStruct() throws Throwable {
Linker linker = Linker.nativeLinker();
SymbolLookup symbolLookup = SymbolLookup.loaderLookup();
MethodHandle test_point = linker.downcallHandle(
symbolLookup.find("test_point").orElseThrow(),
FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG)
);
StructLayout structLayout = MemoryLayout.structLayout(
JAVA_INT.withName("x"),
JAVA_INT.withName("y"));
SequenceLayout ptsLayout = MemoryLayout.sequenceLayout(10, structLayout);
VarHandle xHandle // (MemorySegment, long) -> int
= ptsLayout.varHandle(PathElement.sequenceElement(),
PathElement.groupElement("x"));
VarHandle yHandle // (MemorySegment, long) -> int
= ptsLayout.varHandle(PathElement.sequenceElement(),
PathElement.groupElement("y"));
MemorySegment segment = Arena.ofAuto().allocate(ptsLayout);
for (int i = 0; i < ptsLayout.elementCount(); i++) {
xHandle.set(segment,
/* index */ (long) i,
/* value to write */ i); // x
yHandle.set(segment,
/* index */ (long) i,
/* value to write */ i); // y
}
MemorySegment result = (MemorySegment) test_point.invoke(segment, ptsLayout.elementCount());
result = result.reinterpret(structLayout.byteSize());
System.out.println(result.getAtIndex(JAVA_INT, 0));
}
I see zero length, I try to use a method to modify the zero length.
I still can't get it, it gives the following error.
Exception in thread "main" java.lang.IllegalArgumentException: Misaligned access at address: 38654705673
at java.base/java.lang.invoke.VarHandleSegmentViewBase.newIllegalArgumentExceptionForMisalignedAccess(VarHandleSegmentViewBase.java:57)
at java.base/java.lang.invoke.VarHandleSegmentAsInts.offsetNoVMAlignCheck(VarHandleSegmentAsInts.java:100)
at java.base/java.lang.invoke.VarHandleSegmentAsInts.get(VarHandleSegmentAsInts.java:111)
at java.base/java.lang.foreign.MemorySegment.getAtIndex(MemorySegment.java:1921)
at org.example/org.example.TestNative.dereferenceSegmentsStruct(TestNative.java:109)
at org.example/org.example.TestNative.main(TestNative.java:33)
What do I need to do to read the x and y of the Point returned in C++?
Fortunately, with the help of Holger and Jorn Vernee, I modified the code and successfully ran it. The following modifications have been made
extern "C" MATHLIBRARY_API Point test_point(Point points[], long count);
public static void dereferenceSegmentsStruct() throws Throwable {
StructLayout structLayout = MemoryLayout.structLayout(
JAVA_INT.withName("x"),
JAVA_INT.withName("y"));
MethodHandle test_point = linker.downcallHandle(
symbolLookup.find("test_point").orElseThrow(),
FunctionDescriptor.of(structLayout, ADDRESS, JAVA_LONG)
);
SequenceLayout ptsLayout = MemoryLayout.sequenceLayout(10, structLayout);
VarHandle xHandle // (MemorySegment, long) -> int
= ptsLayout.varHandle(PathElement.sequenceElement(),
PathElement.groupElement("x"));
VarHandle yHandle // (MemorySegment, long) -> int
= ptsLayout.varHandle(PathElement.sequenceElement(),
PathElement.groupElement("y"));
MemorySegment segment = Arena.ofAuto().allocate(ptsLayout);
for (int i = 0; i < ptsLayout.elementCount(); i++) {
xHandle.set(segment,
/* index */ (long) i,
/* value to write */ i); // x
yHandle.set(segment,
/* index */ (long) i,
/* value to write */ i); // y
}
SegmentAllocator allocator = SegmentAllocator.slicingAllocator(Arena.ofAuto().allocate(100));
MemorySegment result = (MemorySegment) test_point.invoke(allocator, segment, ptsLayout.elementCount());
System.out.println(result);
result = result.reinterpret(structLayout.byteSize());
VarHandle resultX // (MemorySegment, long) -> int
= structLayout.varHandle(PathElement.groupElement("x"));
VarHandle resultY // (MemorySegment, long) -> int
= structLayout.varHandle(PathElement.groupElement("y"));
System.out.println(StringTemplate.STR. "\{ resultX.get(result) }:\{ resultY.get(result) }" );
}