ventgrey
ventgrey
DDeno
Created by ventgrey on 10/9/2024 in #help
2.0 node_modules directory approach breaks when using private npm packages.
I think there is already an issue that I can link to this. I've started redacting my issue though, https://github.com/denoland/deno/issues/23266
10 replies
DDeno
Created by ventgrey on 10/9/2024 in #help
2.0 node_modules directory approach breaks when using private npm packages.
Okay, I'll open one 🙂 I've got even more context. It seems that the underlying issue is with libraries that depend on npm packages that need external FFI mods, this results in the deno compile command running correctly but not inserting the main ESM script in the final binary
10 replies
DDeno
Created by ventgrey on 10/9/2024 in #help
2.0 node_modules directory approach breaks when using private npm packages.
Is it too late for this? Any extra context that I need to add in such issue? 🤔
10 replies
DDeno
Created by ventgrey on 10/9/2024 in #help
2.0 node_modules directory approach breaks when using private npm packages.
Update: Apparently bcrypt might not be compatible with deno 2.0 as the deno compile binary doesn't find the library if it's being used as a library dependency.
10 replies
DDeno
Created by ventgrey on 10/9/2024 in #help
2.0 node_modules directory approach breaks when using private npm packages.
Fixed by keeping deps inside a minimal package.json file and the important stull like import maps inside deno.json it's kind of carcinogenic but it does the job 👍
10 replies
DDeno
Created by Mr. Wayne 🇵🇸 on 7/5/2024 in #help
Mongoose Type Error
This no longer works even with @types/mongoose 😦
6 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
This is the Golang code used to generate the dynamic library for the Denosaurs example:
package main

import (
"encoding/json"
"fmt"
"unsafe"
)

/*
#include <stdlib.h>
*/
import "C"

//export Denosaur
type Denosaur struct {
Species string `json:"species"`
Colour string `json:"colour"`
Discovered string `json:"discovered"`
}

//export SearchByDenoSpecies
func SearchByDenoSpecies(denosJSON *C.char, speciesName *C.char) *C.char {
var denos []Denosaur

err := json.Unmarshal([]byte(C.GoString(denosJSON)), &posts)
if err != nil {
return C.CString(fmt.Sprintf("Error: %s", err)) // <-- Memory leak :(
}

searchSpecies := C.GoString(speciesName)

for _, deno := range denos {
if deno.Species == searchSpecies {
result, _ := json.Marshal(deno)
return C.CString(string(result)) // <-- Another memory leak :((
}
}

var notFountStr *C.char = C.CString(fmt.Sprintf("Not found: %s", searchSpecies))
defer C.free(unsafe.Pointer(notFountStr)) // <-- Memory Leakn't :)
return notFountStr
}

func main() {}
package main

import (
"encoding/json"
"fmt"
"unsafe"
)

/*
#include <stdlib.h>
*/
import "C"

//export Denosaur
type Denosaur struct {
Species string `json:"species"`
Colour string `json:"colour"`
Discovered string `json:"discovered"`
}

//export SearchByDenoSpecies
func SearchByDenoSpecies(denosJSON *C.char, speciesName *C.char) *C.char {
var denos []Denosaur

err := json.Unmarshal([]byte(C.GoString(denosJSON)), &posts)
if err != nil {
return C.CString(fmt.Sprintf("Error: %s", err)) // <-- Memory leak :(
}

searchSpecies := C.GoString(speciesName)

for _, deno := range denos {
if deno.Species == searchSpecies {
result, _ := json.Marshal(deno)
return C.CString(string(result)) // <-- Another memory leak :((
}
}

var notFountStr *C.char = C.CString(fmt.Sprintf("Not found: %s", searchSpecies))
defer C.free(unsafe.Pointer(notFountStr)) // <-- Memory Leakn't :)
return notFountStr
}

func main() {}
you may compile this using: go build -o ./<output_dir> -buildmode=c-shared .<input_go_file.
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
// src/routes/denos/mod.ts
import { Context, Hono } from '@hono/hono'; // <-- Install with "deno add @hono/hono"
import { readDinosaursJSON } from '$lib/files'; // <-- Implement your own (use a JSON generator online)
import logger from '$lib/logger'; // <-- Implement your own (example uses winston)
import { libGoDenos } from '$lib/ffi';

const app: Hono = new Hono();

app.get('/species/:name', async (c: Context) => {
const name: string = c.req.param('name');
const denos: string = await readDinosaursJSON('denos');

const encodedName: Uint8Array = new TextEncoder().encode(name);
const encodedDenos: Uint8Array = new TextEncoder().encode(denos + '\0');

const resultPtr: Deno.PointerValue<unknown> = libGoDenos.symbols.SearchByDenoSpecies(
encodedDenos,
encodedName,
);

// if (resultPtr) {...}
if (resultPtr !== null) {
const ret: Deno.UnsafePointerView = new Deno.UnsafePointerView(resultPtr);
const resultString: string = ret.getCString();

c.status(200);
return c.json(JSON.parse(resultString));

} else {
logger.warn(
`Got null result pointer when searching for denos by species: ${name} using the FFI`,
);

c.status(404);
return c.json({
error: 'No denos found',
message: 'FFI error',
});
}
});

export default app;
// src/routes/denos/mod.ts
import { Context, Hono } from '@hono/hono'; // <-- Install with "deno add @hono/hono"
import { readDinosaursJSON } from '$lib/files'; // <-- Implement your own (use a JSON generator online)
import logger from '$lib/logger'; // <-- Implement your own (example uses winston)
import { libGoDenos } from '$lib/ffi';

const app: Hono = new Hono();

app.get('/species/:name', async (c: Context) => {
const name: string = c.req.param('name');
const denos: string = await readDinosaursJSON('denos');

const encodedName: Uint8Array = new TextEncoder().encode(name);
const encodedDenos: Uint8Array = new TextEncoder().encode(denos + '\0');

const resultPtr: Deno.PointerValue<unknown> = libGoDenos.symbols.SearchByDenoSpecies(
encodedDenos,
encodedName,
);

// if (resultPtr) {...}
if (resultPtr !== null) {
const ret: Deno.UnsafePointerView = new Deno.UnsafePointerView(resultPtr);
const resultString: string = ret.getCString();

c.status(200);
return c.json(JSON.parse(resultString));

} else {
logger.warn(
`Got null result pointer when searching for denos by species: ${name} using the FFI`,
);

c.status(404);
return c.json({
error: 'No denos found',
message: 'FFI error',
});
}
});

export default app;
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
For anyone that may get stuck with this in the future, here is the whole code for Deno + Hono API endpoint using the dinosaurs example earlier:
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
Well..that solved it 🤡 .
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
I'm sorry but deno check states otherwise:
TS2345 [ERROR]: Argument of type 'PointerValue<unknown>' is not assignable to parameter of type 'PointerObject<unknown>'.
Type 'null' is not assignable to type 'PointerObject<unknown>'.
const ret = new Deno.UnsafePointerView(resultPtr);
TS2345 [ERROR]: Argument of type 'PointerValue<unknown>' is not assignable to parameter of type 'PointerObject<unknown>'.
Type 'null' is not assignable to type 'PointerObject<unknown>'.
const ret = new Deno.UnsafePointerView(resultPtr);
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
I'm already at that stage. Using text encoders to feed Uint8Array into the function buffer parameters. However, this response troubles me as step 4 is still the exact same type specifically a Deno.PointerValue<unknown>. Deno still whines about types when doing a new UnsafePointerView. Trying to change the PointerValue from unknown to anything else makes the type checker angry as well.
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
Apologies in advance if my tone might be interpreted as un-supportive or if the text length is not adequate.
13 replies
DDeno
Created by ventgrey on 7/25/2024 in #help
Help with FFI strings
[CONTINUE 1] Then I decided to see how others do it and I ended up in the Bun docs. Which has an interesting take when it comes to strings (not providing link to avoid spamming more links) but goes like this: JavaScript strings and C-like strings are different, and that complicates using strings with native libraries. OK, so maybe a "CString" like Bun it's what I need. I found Deno issue #14248 where a Deno release is mentioned, and there, in a codeblock an example of such method is used and it requires yer another UnsafePointerView object, neither pointer nor buffer work for this approach. Which leads me to think, that nothing that returns char* is remotely usable in the FFI and should return a uint8 instead (?) https://docs.deno.com/api/deno/~/Deno.UnsafePointerView Docs also go nowhere when explaining such returned types. Don't get me wrong, this is probably a 99.9% skill issue by me. So, if returning any pointer of buffer from dylib is the same as doing nothing. Why is the PointerValue a returned thing if that is supposed to return a PointerObject? Why is that not documented? How can I help with that documentation if I manage to figure this out? Does a PointerValue instead of a PointerObject mean i messed up somewhere in the compiled language? I thought this was possible in the past because some stackoverflow answers point that pointer is old and work must be done with Uint8Array if you want to somehow handle the function results. When was this changed? was 1.14 the only release with changes to the FFI?
13 replies