node-ffi-napi / ref-napi

Turn Buffer instances into "pointers"
MIT License
123 stars 67 forks source link

How to read at specific memory address? #74

Closed masinamichele closed 2 years ago

masinamichele commented 2 years ago

Hello, Returning from a C++ function, I have a size_t size representing the size of a certain list and a int* head pointing to the memory address of the first element of the same list.

I can access the head value without any problem using .deref() and see it's memory address with .hexAddress(), but my question is how to read the next elements.

If I could create a ref pointing to a specific memory address, I could loop over the size and create an offset starting at head, reading each time at head.hexAddress() + offset, but I cannot find a way to do that.

Am I trying the right way or is there some method I'm missing?

Thank you for any help.

masinamichele commented 2 years ago

Hello, I solved this problem myself, also watching some old issues of the original ref package.

I have a struct:

import refStruct from "ref-struct-di";
const CStruct = refStruct(ref);
const ImageResult = CStruct({
  size: "size_t",
  head: "int*",
});

I then call the ffi, which expects a pointer to the aforementioned struct:

const out = new ImageResult();
lib.load_image(out.ref());
const json = out.toJSON();

The size and head properties are the ones mentioned in the original post of this issue.

To read the whole array starting at head, I can do the following:

let imageData = Buffer.alloc(ref.sizeof.pointer);
imageData.writePointer(json.head);
imageData = imageData.readPointer(0, ref.sizeof.int * json.size);

// Imperative approach
const values = [];
for (let i = 0; i < json.size; i++) {
  const ptr = ref.get(imageData, i * ref.sizeof.int, ref.types.int);
  values.push(ptr);
}

// Declarative approach
const values = Array.from({ length: json.size }, (_, i) => ref.get(imageData, i * ref.sizeof.int, ref.types.int));

Inside values I then have the whole array.

Hope that helps.

freehere107 commented 2 years ago

@masinamichele I have the same problem as you, but I am reading an array, something like this, but the data I read is wrong

    it('decode [u32;6]', (): void => {
       // 'fixU32_decode': [ref.refType("uint32"), ['string']],
       // unsigned int* fixU32_decode(char* raw);
        let value = libm.fixU32_decode("010000000200000003000000040000000500000006000000")

        let buf = Buffer.alloc(ref.sizeof.pointer);
        buf.writePointer(value);
        let uint32Size = ref.sizeof.uint32
        buf = buf.readPointer(0, uint32Size * 6);

        const values = [];
        for (let i = 0; i < 6; i++) {
            const ptr = ref.get(buf, i * uint32Size, ref.types.uint32);
            values.push(ptr);
        }
        console.log(values)
        // ref.writePointer(buf, 0, value)
        // const out = ref.readPointer(buf, 0, 24);

        expect(
            JSON.stringify([1, 2, 3, 4, 5, 6])
        ).toEqual(values); // there will return [ 1, 1843188112, 1, 0, 0, 1843188192 ]
    });

can you help me look at this problem, thank you