Search code examples
typescriptdeno

How to use a double pointer in Deno


I'm just wondering if there is a way to copy a TypeScript buffer to a C char**? I tried, but, I'm sure I missed something.

  1. C call Deno callback with char** as parameter
  2. Deno creates a buffer and updates it with some string
  3. Deno set the buffer address to the char**
  4. C reads back the Deno string

If you like a complete working full example is here.

deno 1.31.1 (release, x86_64-pc-windows-msvc)
v8 11.0.226.13
typescript 4.9.4

C Code

void test() {

    char* Buffer;

    call_deno_function((char**)&Buffer);
    
    printf("The Deno response is %s", Buffer); // Should print "Hello" but it prints "null"
}

Deno TypeScript Code

export function bind(win, element, func) : number {

    const callbackResource = new Deno.UnsafeCallback(
        {
            parameters: [
                   'pointer' // <------ This is char**
                   ],
            result: 'void',
        } as const,
        (
            param_response: Deno.Pointer,
        ) => {

            console.log("This is Deno callback function...");

            const result = String("Hello");

            // `result`         : The callback result in string
            // `param_response` : It's a non initialized (null) `char**`

            // Now, we should create a non-garbage colleted buffer, fill it with `result`
            // and set it to `param_response`.

            // Create A Buffer
            // This code is by ChatGPT (AI)
            const encoder = new TextEncoder(); // Create a TextEncoder instance
            const resultBytes = encoder.encode(result); // Convert the string to bytes
            const buf = new Uint8Array(resultBytes.length + 1); // Allocate a buffer to hold the string
            buf.set(resultBytes); // Copy the bytes of the string into the buffer
            buf[resultBytes.length] = 0; // Set the null terminator

            // Set our buffer `buf` to `char**`
            param_response = buf; // <---------- This is not working
        },
);

Output

This is Deno callback function...
The Deno response is null

Expected

This is Deno callback function...
The Deno response is Hello

Solution

  • A core Deno developer helped me to solve this. I'm sharing it if any one needs it.

    export function bind(win, element, func) : number {
    
        const callbackResource = new Deno.UnsafeCallback(
            {
                parameters: [
                       'pointer' // <------ This is char**
                       ],
                result: 'void',
            } as const,
            (
                param_response: Deno.PointerValue,
            ) => {
    
                // param response is a pointer to a memory slot large enough to keep a pointer
                const target = new BigUint64Array(Deno.UnsafePointerView.getArrayBuffer(param_response, 8); // 8 bytes ie. pointer size on a 64 bit machine, use BigUin64Array to get a writable and suitable view into it.
                const stringBuffer = new TextEncoder().encode("Hello\0");
                target[0] = BigInt(Deno.UnsafePointer.value(Deno.UnsafePointer.of(stringBuffer))); // Write our string response buffer address into the `param_response` memory slot.
            },
    );