Coder Social home page Coder Social logo

rainwayapp / node-clangffi Goto Github PK

View Code? Open in Web Editor NEW
7.0 7.0 1.0 939 KB

Generate Typescript FFI bindings for C/C++ libraries using libclang and ffi-napi.

License: MIT License

JavaScript 5.93% TypeScript 93.71% C 0.37%
ffi ffi-bindings generator libclang nodejs typescript

node-clangffi's People

Contributors

bengreenier avatar github-actions[bot] avatar lynn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

tamuratak

node-clangffi's Issues

Support copying comments

It should be possible for us to map in comments. We should further evaluate and consider doing so.

It's worth noting that due to how ffi.Library() works, we won't be able to easily name parameters, which may make some comments fairly confusing.

flag --no-prettier not working

when giving --no-prettier, prettier is still used.

Using set DEBUG=clangffi to log cli arguments object, it's clear that noPrettier value is still false.

Ensure all primitive types are mapped properly

Currently, a best-effort set of primitives is mapped in tsgen/resolve.ts. However, we should ensure that the list covers all types that ref.types knows how to represent, which should, by extension, be all valid primitive types.

If you're reading this issue, it might be because a type is missing. To debug, use set DEBUG=clangffi:tsgen:resolve and look for your type. The output should make it clear if it was resolved as a "builtin" or "unknown" type. If you believe it to be a primitive but it's showing up as "unknown", we need to add it to these lookup tables.

Move to absolute urls in README

Now that this repo is public, we should move to absolute URLs for links in the README.md files, so that they work from npm as well.

Support enums of different sizes

#[repr(u8)]
#[derive(Debug, Display, Copy, Clone, Eq, PartialEq)]
pub enum RainwayChannelMode {
    Unreliable = 0,
    Reliable = 1,
}

Take this perfectly innocuous looking enum in Rust. It generates this wonderfully correct C/C++ header definition via cbindgen:

enum RainwayChannelMode
#ifdef __cplusplus
  : uint8_t
#endif // __cplusplus
 {
  Unreliable = 0,
  Reliable = 1,
};
#ifndef __cplusplus
typedef uint8_t RainwayChannelMode;
#endif // __cplusplus

But then node-clangffi seems to think it is a bit confusing because it ends up generating

export enum RainwayChannelMode {
  Unreliable = 0,
  Reliable = 1,
}
export type RainwayChannelMode = number;
// ...
export const RainwayChannelModeDef = ref.types.int;
export const RainwayChannelModeDef = ref.types.uint8;

Basically we need the uint8_t typedef to override the size, but to only keep the enum definition.

Function decl with void argument fails

If given a header with the following:

typedef void (*MyFunctionPointer)(void);

Then clangffi will generate:

export type MyFunctionPointer(arg0:) => void;

which is invalid. It should instead generate:

export type MyFunctionPointer() => void;

Support custom preprocessor definitions

We should provide a way for a user to call clangffi specifying some flags to define symbols. E.g. -DDEBUG=1 to define DEBUG=1.

This should work similarly to clang /D <macro=value> here

Pass FnPtr params as ffi.Callback

Sometimes we may wish to use ffi.Callback to represent a function pointer that's being passed to a native function as a parameter. Today, these types get mapped as ffi.Function which isn't compatible. We should consider how to support a typed solution that allows either:

  • Select ffi.Function or ffi.Callback via clangffi flags or other user config (ideally selection occurs at a function level)
  • Provide a typing that allows for either, and let the caller decide

Use `UnderlyingType` for *Type exports

There is still some inconsistency between what a *Def stores, and what a *Type represents. To avoid this, it's probably better to use UnderlyingType from ref-napi rather than generating it ourselves. E.g:

type MyStructType = UnderlyingType<typeof MyStructDef>;

instead of

type MyStructType = StructObject<MyStruct>;

since the TS typing and the coerced ref-napi NamedType may not align exactly.

Appears to not ever load `libclang` on my system. What can I do?

How exactly do I need to provide libclang? Is it libclang.so or a binary named libclang? I've built LLVM on my system and provided both its libclang.so and the one in PATH, but I still can't get any more output than what's below. It seems like clangffi isn't using the libclang I'm providing.

import ffi from "ffi-napi";
import ref, { Pointer as TypedPointer, UnderlyingType } from "ref-napi";
import refStructDi, { StructObject } from "ref-struct-di";
import refArrayDi, { TypedArray } from "ref-array-di";
import refUnionDi from "ref-union-di";
const Struct = refStructDi(ref);
const Union = refUnionDi(ref);
const ArrayType = refArrayDi(ref);
const Pointer = ref.refType;
export function dlopen(libPath: string) {
  return ffi.Library(libPath, {});
}

Select OSS license

We need to close on what OSS license to use, and then update the following:

  • package.json (license field, in all projects)
  • LICENSE file
  • README.md language (in root)

support attributed types

Today CXTypeKind.CXType_Attributed isn't well supported. We should be able to get the modified type via the Type model.

faster CI integration tests

The current CI "integration" test is to walk libclang v13 and ensure we find the same types in it each time. This is good for ensuring we can always regenerate libclang-bindings using libclang-bindings but probably doesn't need to happen for validation of a PR, given it takes upwards of 15m in CI.

We should instead introduce a smaller integration test(s) that give us similar confidence, but execute much more quickly. Further, rather then just removing the existing one, we could consider instead running that only on check-in to main (after PR has been merged) for added confidence, but without slowing down the inner loop.

Crash while generating bindings for ObjectBox

Hi,

I am trying to generate bindings for ObjectBox but clangffi keeps crashing with the following error:

  clangffi {
  clangffi   "_": [],
  clangffi   "lib-path": "/usr/lib/x86_64-linux-gnu/libclang-14.so",
  clangffi   "libPath": "/usr/lib/x86_64-linux-gnu/libclang-14.so",
  clangffi   "i": "objectbox.h",
  clangffi   "input": "objectbox.h",
  clangffi   "o": "objectbox.ts",
  clangffi   "output": "objectbox.ts",
  clangffi   "default-symbols": false,
  clangffi   "defaultSymbols": false,
  clangffi   "L": "c",
  clangffi   "language": "c",
  clangffi   "I": [],
  clangffi   "include-directory": [],
  clangffi   "includeDirectory": [],
  clangffi   "D": [],
  clangffi   "define": [],
  clangffi   "R": [],
  clangffi   "hard-remap": [],
  clangffi   "remap": [],
  clangffi   "hardRemap": [],
  clangffi   "crlf": false,
  clangffi   "prettier": true,
  clangffi   "include": [],
  clangffi   "include-file": [],
  clangffi   "includeFile": [],
  clangffi   "exclude": [],
  clangffi   "clean-enum-constants": true,
  clangffi   "cleanEnumConstants": true,
  clangffi   "$0": "clangffi"
  clangffi } +0ms
  clangffi:tsgen open(objectbox.ts): begin +0ms
  clangffi:tsgen open(objectbox.ts): end +1ms
  clangffi:parser skip '__u_char' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +0ms
  clangffi:parser skip '__u_short' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +16ms
  clangffi:parser skip '__u_int' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +17ms
  clangffi:parser skip '__u_long' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +19ms
  clangffi:parser skip '__int8_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +14ms
  clangffi:parser skip '__uint8_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +16ms
  clangffi:parser skip '__int16_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +17ms
  clangffi:parser skip '__uint16_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +15ms
  clangffi:parser skip '__int32_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +16ms
  clangffi:parser skip '__uint32_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +15ms
  clangffi:parser skip '__int64_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +16ms
  clangffi:parser skip '__uint64_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +15ms
  clangffi:parser skip '__int_least8_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +19ms
  clangffi:parser skip '__uint_least8_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +18ms
  clangffi:parser skip '__int_least16_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +15ms
  clangffi:parser skip '__uint_least16_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +16ms
  clangffi:parser skip '__int_least32_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +14ms
  clangffi:parser skip '__uint_least32_t' from '/usr/include/x86_64-linux-gnu/bits/types.h'. +15ms


#
# Fatal error in , line 0
# Check failed: result.second.
#
#
#
#FailureMessage Object: 0x7ffee494ace0
 1: 0xb76401  [node]
 2: 0x1c09824 V8_Fatal(char const*, ...) [node]
 3: 0xfcecd1 v8::internal::GlobalBackingStoreRegistry::Register(std::shared_ptr<v8::internal::BackingStore>) [node]
 4: 0xd20518 v8::ArrayBuffer::GetBackingStore() [node]
 5: 0xabdc90 napi_get_typedarray_info [node]
 6: 0x7f0f95c053ac  [/home/thecodrr/.npm/_npx/0a8e200cae307ad8/node_modules/ref-napi/prebuilds/linux-x64/node.napi.node]
 7: 0x7f0f95c05b48  [/home/thecodrr/.npm/_npx/0a8e200cae307ad8/node_modules/ref-napi/prebuilds/linux-x64/node.napi.node]
 8: 0x7f0f95c07831  [/home/thecodrr/.npm/_npx/0a8e200cae307ad8/node_modules/ref-napi/prebuilds/linux-x64/node.napi.node]
 9: 0x7f0f95c0d4ab Napi::details::CallbackData<void (*)(Napi::CallbackInfo const&), void>::Wrapper(napi_env__*, napi_callback_info__*) [/home/thecodrr/.npm/_npx/0a8e200cae307ad8/node_modules/ref-napi/prebuilds/linux-x64/node.napi.node]
10: 0xab45dd  [node]
11: 0xd5531e  [node]
12: 0xd5673f v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
13: 0x15f2199  [node]
Trace/breakpoint trap (core dumped)

I am running the following command:

DEBUG=clangffi* npx clangffi --lib-path /usr/lib/x86_64-linux-gnu/libclang-13.so -i objectbox.h -o objectbox.ts

Node v16.15.1
libclang v13

Header file: https://raw.githubusercontent.com/objectbox/objectbox-c/main/include/objectbox.h

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.