diff --git a/core/src/fr/hammons/slinc/Mem.scala b/core/src/fr/hammons/slinc/Mem.scala index 68ea1eb2..22c7c18e 100644 --- a/core/src/fr/hammons/slinc/Mem.scala +++ b/core/src/fr/hammons/slinc/Mem.scala @@ -12,6 +12,7 @@ trait Mem: def writeShort(v: Short, offset: Bytes): Unit def writeByte(v: Byte, offset: Bytes): Unit def writeByteArray(v: Array[Byte], offset: Bytes): Unit + def writeAddress(v: Mem, offset: Bytes): Unit def writeInt(v: Int, offset: Bytes): Unit def writeIntArray(v: Array[Int], offset: Bytes): Unit diff --git a/core/src/fr/hammons/slinc/Send.scala b/core/src/fr/hammons/slinc/Send.scala index 32f7221d..fa8aef9d 100644 --- a/core/src/fr/hammons/slinc/Send.scala +++ b/core/src/fr/hammons/slinc/Send.scala @@ -173,3 +173,10 @@ object Send: while i < value.length do s.to(mem, offset + (l.layout.size * i), value(i)) i += 1 + + private val ptrSend: Send[Ptr[Any]] = new Send[Ptr[Any]]: + def to(mem: Mem, offset: Bytes, value: Ptr[Any]): Unit = + mem.writeAddress(value.mem, offset) + + + given sendPtr[A]: Send[Ptr[A]] = ptrSend.asInstanceOf[Send[Ptr[A]]] diff --git a/core/test/resources/native/test.c b/core/test/resources/native/test.c index 2b99e3d4..e2657fff 100644 --- a/core/test/resources/native/test.c +++ b/core/test/resources/native/test.c @@ -6,4 +6,13 @@ EXPORTED int identity_int(int i) { return i; +} + +struct I31Struct { + const char* field; + +}; + +EXPORTED const char* i31test(struct I31Struct i31Struct) { + return i31Struct.field; } \ No newline at end of file diff --git a/core/test/src/fr/hammons/slinc/BindingSpec.scala b/core/test/src/fr/hammons/slinc/BindingSpec.scala index 0d2ca39d..6aeb8df8 100644 --- a/core/test/src/fr/hammons/slinc/BindingSpec.scala +++ b/core/test/src/fr/hammons/slinc/BindingSpec.scala @@ -3,12 +3,24 @@ package fr.hammons.slinc import munit.ScalaCheckSuite trait BindingSpec(val slinc: Slinc) extends ScalaCheckSuite: - import slinc.{given,*} + import slinc.{given, *} @LibraryName("@test") object Test derives Library: def identity_int(i: CInt): CInt = Library.binding + // issue 31 test binding + def i31test(struct: I31Struct): Ptr[CChar] = Library.binding + + case class I31Struct(field: Ptr[CChar]) derives Struct test("int_identity") { assertEquals(Test.identity_int(5), 5) } + test("issue 31 fix") { + Scope.confined { + val struct = Test.I31Struct( + Ptr.copy("hello world!") + ) + Test.i31test(struct) + } + } diff --git a/j17/src/fr/hammons/slinc/Mem17.scala b/j17/src/fr/hammons/slinc/Mem17.scala index 65b7f613..0607b60d 100644 --- a/j17/src/fr/hammons/slinc/Mem17.scala +++ b/j17/src/fr/hammons/slinc/Mem17.scala @@ -4,6 +4,7 @@ import jdk.incubator.foreign.MemorySegment import jdk.incubator.foreign.MemoryAccess import jdk.incubator.foreign.ResourceScope import jdk.incubator.foreign.CLinker.{C_CHAR, C_INT} +import jdk.incubator.foreign.Addressable class Mem17(private[slinc] val mem: MemorySegment) extends Mem: override def readDouble(offset: Bytes): Double = @@ -60,6 +61,9 @@ class Mem17(private[slinc] val mem: MemorySegment) extends Mem: override def writeShort(v: Short, offset: Bytes): Unit = MemoryAccess.setShortAtOffset(mem, offset.toLong, v) + override def writeAddress(v: Mem, offset: Bytes): Unit = + MemoryAccess.setAddress(mem, v.asBase.asInstanceOf[Addressable]) + override def readByte(offset: Bytes): Byte = MemoryAccess.getByteAtOffset(mem, offset.toLong) diff --git a/j19/src/fr/hammons/slinc/Mem19.scala b/j19/src/fr/hammons/slinc/Mem19.scala index bd39e1bc..393aca2a 100644 --- a/j19/src/fr/hammons/slinc/Mem19.scala +++ b/j19/src/fr/hammons/slinc/Mem19.scala @@ -3,6 +3,7 @@ package fr.hammons.slinc import java.lang.foreign.MemorySegment import java.lang.foreign.MemorySession import java.lang.foreign.ValueLayout, ValueLayout.* +import java.lang.foreign.Addressable object Mem19: val javaShort = JAVA_SHORT.nn.withBitAlignment(8) @@ -76,6 +77,8 @@ class Mem19(private[slinc] val mem: MemorySegment) extends Mem: override def readShort(offset: Bytes): Short = mem.get(javaShort, offset.toLong) + def writeAddress(v: Mem, offset: Bytes): Unit = mem.set(javaAddress, offset.toLong, v.asBase.asInstanceOf[Addressable]) + override def readIntArray(offset: Bytes, size: Int): Array[Int] = val arr = Array.ofDim[Int](size) val resizedMem = resizeSegment(Bytes(size * javaInt.nn.byteSize()))