typescriptffideno

When using FFI with Deno how to deal with struct returned by a C function?


I have a C function that returns a struct CommandList, like below

typedef struct Command {
  enum CommandId id;
  const char *arg1;
  const char *arg2;
} Command;

typedef struct CommandList {
  const struct Command *test_commands;
  uintptr_t len;
} CommandList;

I have declared it like this

const dylib = Deno.dlopen(
  libName,
  {
    load_scenario: { parameters: ["buffer"], result: { struct: CommandList } },
    free_test: { parameters: [{ struct: CommandList }], result: "void" },
  } as const,
  );

the call

console.log(dylib.symbols.load_scenario(buf));

prints

Uint8Array(16) [
  112, 61, 21, 11, 167, 85,
    0,  0,  7,  0,   0,  0,
    0,  0,  0,  0
]

That looks correct as I know that there is 7 elements in the array, but how could I map this struct to something less raw than a Uint8array?

Is there any way to map this array to let's say:

interface Command {
    id: Uint32Array,
    arg1: Deno.UnsafePointerView<Uint8Array>;
    arg2: Deno.UnsafePointerView<Uint8Array>;
}

interface CommandList {
    data: Deno.UnsafePointerView<Command>;
    len: number;
}

In the end I would like to write code like this:

  const command_list: CommandList = dylib.symbols.load_scenario(buf);

  for (let i = 0; i < command_list.len; i++) {
    const command: Command = command_list.data[i];
    console.log(command.id, command.arg1, command.arg2);
  }

I've read the doc, dig through Deno ffi tests https://raw.githubusercontent.com/littledivy/deno/21e77c01b75e6f9fda320b4abf56433acb63bbc5/test_ffi/tests/test.js and googled a lot with no luck


Solution

  • A Uint8Array is backed by an array buffer. You can access the raw buffer and then use it to construct a DataView. A DataView can be used to access different types of data in the buffer.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView