Skip to content

Commit

Permalink
handle typedef with postfix struct name; bunAllocArray hepler added
Browse files Browse the repository at this point in the history
  • Loading branch information
Morglod committed Sep 29, 2024
1 parent 187c7be commit 6c03a32
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
generate-wgpu-bindings_cache_*.json
test-bindings_cache_*.json
generate-bindings_tmp_exec
example.ts
lib
bindings_cache_*
test_out.ts


# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

Expand Down
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
node_modules
generate-wgpu-bindings_cache_*.json
test-bindings_cache_*.json
generate-bindings_tmp_exec
example.ts
src
test.h
test.ts
.vscode
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Debug File",
"program": "test.ts",
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": true
}
]
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Will exec `clang` to get ast and type infos, so it should be available in PATH.

Feel free to write an issue with your header file, so I could tweak this package.

Tested on clang13 & bun 1.0.2 (upper versions requests macos update, goodbye bun)

## Install

```
Expand Down
Binary file modified bun.lockb
Binary file not shown.
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bun-ffi-gen",
"version": "1.1.2",
"version": "1.1.3",
"module": "lib/index.ts",
"description": "FFI bindings generator for Bun",
"type": "module",
Expand Down Expand Up @@ -29,11 +29,12 @@
"url": "git+https://github.com/Morglod/bun-ffi-gen.git"
},
"devDependencies": {
"typescript": "^5.0.0",
"bun-types": "^1.0.33"
"typescript": "^5.0.0"
},
"peerDependencies": {
"typescript": "^5.0.0",
"bun-types": "^1.0.33"
"typescript": "^5.0.0"
},
"dependencies": {
"@types/bun": "^1.0.2"
}
}
4 changes: 4 additions & 0 deletions src/clang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export function clangGetSizeOf(headerPath: string, cTypeName: string, cache?: Cl
return cache.sizeOf[cacheName];
}

logInfo(`clangGetSizeOf "${cTypeName}"`);

const code = `
#include "${headerPath}"
#include <stdio.h>
Expand All @@ -118,6 +120,8 @@ export function clangGetOffsetOf(headerPath: string, cTypeName: string, fieldNam
return cache.offsetOf[cacheName];
}

logInfo(`clangGetOffsetOf "${cTypeName}"."${fieldName}"`);

const code = `
#include "${headerPath}"
#include <stdio.h>
Expand Down
8 changes: 8 additions & 0 deletions src/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ export function bunReadArray<T>(from: Pointer | TypedArrayPtr<T>, offset: number
return out;
}
export function bunAllocArray<T>(cTypeSize: number, items: T[], itemWriter: (item: T, buffer: Buffer, offset: number) => void): TypedArrayPtr<T> {
const buf = Buffer.alloc(cTypeSize * items.length);
for (let i = 0; i < items.length; ++i) {
itemWriter(items[i], buf, i * cTypeSize);
}
return buf as TypedArrayPtr<T>;
}
export function alloc_CString(str: string) {
return new BunCString(bunPtr(Buffer.from(str + "\\0")) as any);
}
Expand Down
14 changes: 13 additions & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,19 @@ export function parseClangAst(astJson: any[], headerFilePath: string, clangTypeI

// struct
if (statement.kind === "RecordDecl") {
const name = statement.name;
let name = statement.name;

// handle case for typedef struct {} NAME;
if (!name) {
const nextStmt = astJson[statementIndex + 1];
if (nextStmt && nextStmt.kind === "TypedefDecl" && nextStmt.inner?.[0]?.ownedTagDecl.id === statement.id) {
name = nextStmt.name;
statementIndex++;
} else {
logInfo("found RecordDecl without name at ", statement.loc);
continue;
}
}

if (!statement.inner) {
continue;
Expand Down
6 changes: 6 additions & 0 deletions test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
typedef struct {
int a;
int b;
} Foo;

int sum(Foo* f);
57 changes: 57 additions & 0 deletions test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ClangTypeInfoCache, clangGetAstJson, CodeGen, parseClangAst, clangClean, addIncludeDir } from "./src";
import { LogLevel, setLogLevel } from "./src/log";
import path from "path";

const HEADER_PATH = "./test.h";
const TYPE_CACHE_PATH = "./test-bindings_cache";

setLogLevel(LogLevel.verbose);

// add include dirs for clang
addIncludeDir(path.resolve("my_include_dir"));

// get header ast from clang
const wgpuAst = await clangGetAstJson(HEADER_PATH);

// create clang types cache (for sizeof / offsetof)
const clangTypeInfoCache = await ClangTypeInfoCache.create(TYPE_CACHE_PATH);

// parse ast
const result = parseClangAst(wgpuAst, HEADER_PATH, clangTypeInfoCache);

// update clang cache
await clangTypeInfoCache.save();

// prepare code generation
const codeGen = new CodeGen({
// see more options below
funcSymbolsImportLibPathCode(out) {
out.push(`
let _LIB_PATH: string = "";
if (process.platform == "darwin") {
_LIB_PATH =
import.meta.dir +
"/../wgpu/libwgpu_native.dylib";
} else {
throw new Error("not supported wgpu bindings platform");
}
`);

return "_LIB_PATH";
},
});

codeGen.generateAll(result);

if (codeGen.failedSymbols.size) {
console.log("ffi failed for:");
console.log(Array.from(codeGen.failedSymbols));
}

// write output
codeGen.writeToFile("./test_out.ts");

// cleanup
await clangTypeInfoCache.save();
await clangClean();

0 comments on commit 6c03a32

Please sign in to comment.