Last active
August 17, 2021 20:36
-
-
Save timyates/e051d5752231b8a2434d68dfa84fce61 to your computer and use it in GitHub Desktop.
Overlay a struct over a block of memory in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
typedef unsigned char UCHAR; | |
typedef struct rgba | |
{ | |
UCHAR r; | |
UCHAR g; | |
UCHAR b; | |
UCHAR a; | |
} RGBA; | |
void printRgba(RGBA rgba) { | |
printf("[%d, %d, %d, %d]\n", rgba.r, rgba.g, rgba.b, rgba.a); | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
// Space for 100 elements | |
int *block = malloc(100 * sizeof(RGBA)); | |
void *offset = (void*) block; | |
// Overlay our struct over the array, and set some values | |
((RGBA*)offset)->r = 1; | |
((RGBA*)offset)->g = 2; | |
((RGBA*)offset)->b = 3; | |
((RGBA*)offset)->a = 4; | |
// prints [1, 2, 3, 4] | |
printRgba(*(RGBA*)offset); | |
// Move it forward 1 UCHAR | |
offset += sizeof(UCHAR); | |
// prints [2, 3, 4, 0] | |
printRgba(*(RGBA*)offset); | |
free(block); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// And similar in Panama (Azul java 16.0.2 with --add-modules jdk.incubator.foreign) | |
package com.bloidonia; | |
import jdk.incubator.foreign.GroupLayout; | |
import jdk.incubator.foreign.MemoryLayout; | |
import jdk.incubator.foreign.MemoryLayouts; | |
import jdk.incubator.foreign.MemorySegment; | |
import jdk.incubator.foreign.SequenceLayout; | |
import java.lang.invoke.VarHandle; | |
public class Main { | |
public static void main(String[] args) { | |
GroupLayout rgba = MemoryLayout.ofStruct( | |
MemoryLayouts.JAVA_BYTE.withName("r"), | |
MemoryLayouts.JAVA_BYTE.withName("g"), | |
MemoryLayouts.JAVA_BYTE.withName("b"), | |
MemoryLayouts.JAVA_BYTE.withName("a") | |
); | |
SequenceLayout seqStruct = MemoryLayout.ofSequence(100, rgba); | |
VarHandle VHr = seqStruct.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("r")); | |
VarHandle VHg = seqStruct.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("g")); | |
VarHandle VHb = seqStruct.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("b")); | |
VarHandle VHa = seqStruct.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("a")); | |
try(MemorySegment buffer = MemorySegment.allocateNative(seqStruct)) { | |
VHr.set(buffer, 0, (byte)1); | |
VHg.set(buffer, 0, (byte)2); | |
VHb.set(buffer, 0, (byte)3); | |
VHa.set(buffer, 0, (byte)4); | |
MemorySegment memorySegment = buffer.asSlice(1); | |
// prints [2, 3, 4, 0] 😎 | |
System.out.printf("[%d, %d, %d, %d]", (byte)VHr.get(memorySegment, 0), (byte)VHg.get(memorySegment, 0), (byte)VHb.get(memorySegment, 0), (byte)VHa.get(memorySegment, 0)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My interest got piqued by this excellent series of posts from Carl Dea on Project Panama.
Back in the day, I used to love doing this sort of thing, allocating a contiguous block of memory, and then accessing it by overlaying different
structs
to provide context and shape to the chunks.Panama is being actively developed, so the Java I used above (Azul Java 16.0.2 with the preview features turned on) is probably already hopelessly out of date
But fun