跨语言调 C 库:DragonFFI

js_ffi-一个用于调用javascript的FFI库-Rust开发 js_ffi该库在运行时使用Web程序集在浏览器中创建javascript的桥梁外国函数接口(FFI)库用于在运行时使用Web程序集在浏览器中javascript的桥梁用于从Web Assembly调用许多编程语言的Javascript函数,没有代码生成或特殊的商品组件支持基于回调内存的回调(例如setTimeout)期货,这是Rust的参数包装库,可与C或C ++一起使用,请查看此处的示例,键入数组可以在网络工作者中执行此项目有 立即下载

跨语言调用是很方便实用的操作,但其实现并非想象的那么简单,包含有复杂的 ABI 设计、语言间的兼容交互等,本文将介绍一个跨语言调 C 库:DragonFFI。

1、定义

在官方 github 仓库中就有相关的说明,DragonFFI 是 C 语言的 FFI(Foreign Function Interface,外部函数接口)库,使用 C++ 编写,基于 clang/llvm 来实现。

跨语言调用 C ,一般有通过手写胶水代码的(JNI,Python,Ruby)、生成胶水代码的(SWIG)、扩展 C 的(C++,Objective-C)。

而 FFI 即其他语言可以通过它所提供的 API 和绑定来调用 C 语言的函数。

A foreign function interface (FFI) is a mechanism by which aprogram written in one programming language can call routines ormake use of services written in another.
# 比如这里用 python 进行 C 语言函数的调用
import pydffi
CU = pydffi.FFI().cdef("int puts(const char* s);");
CU.funcs.puts("hello world!")

# JIT
# First, declare an FFI context
F = pydffi.FFI()
# Then, compile a module and get a compilation unit
CU = F.compile("int add(int a, int b) { return a+b; }")
# And call the function
print(int(CU.funcs.add(4, 5)))

2、与其他 FFI 库的对比

libffi 是有名的提供 C 语言 FFI 库。但它不支持最近的一些调用约定(calling convention),比如 Linux x64 系统的 Microsoft x64 ABI(Application Binary Interface),而且其每个 ABI 还需要手写汇编,其 ABI 也变得复杂,尤其是在传递结构体类型时。

cffi 是 libffi 当中所提供的 python 绑定,它还使用了 pycparser 来声明接口和类型。但它所使用的 C 语言的解析器不支持 include 和一些函数的 attribute,因此需要自行维护调用 C 库的头文件。

DragonFFI 基于 clang/llvm 实现,得以使用 clang 解析头文件而不用自行适配、可以动态编译(支持 JIT)、支持很多调用约定和函数的 attribute。

DragonFFI 目前支持 Linux、OSX 和 Windows,支持 Intel 32 位和 64 位 CPU。

3、如何解析 C 语言的类型

为了解析 C 语言的类型,我们需要以下的一些基本信息:

  • 函数类型,以及调用约定
  • 结构体:偏移量、名字
  • union/enum:域名(值)

一方面,我们看到 LLVM IR 过于底层(low level),十分复杂;另一方面,Clang AST 又过于抽象(high level),没有一些类型信息(比如结构体布局对齐等)。

比较合适的方式是,使用 LLVM metadata (元数据,描述数据的数据),由 Clang 生成 DWARF(debugging with attributed record formats) 或者 PDB(Program Database) 结构体时产生。它们包含有基本的类型描述信息、函数调用约定。

注:PDB 是一种文件格式,和 DWARF 是一个概念,由微软开发出来,包含有调试信息。

这些 LLVM metadata 的具体例子,就是嵌在 IR 里面的那些标注:

target triple = "x86_64-pc-linux-gnu"
%struct.A = type { i16, i32 }
@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1

define void @print_A(i64) local_unnamed_addr !dbg !7 {
  %2 = trunc i64 %0 to i32
  %3 = lshr i64 %0, 32
  %4 = trunc i64 %3 to i32
  tail call void @llvm.dbg.value(metadata i32 %4, i64 0, metadata !18, metadata !19), !dbg !20
  tail call void @llvm.dbg.declare(metadata %struct.A* undef, metadata !18, metadata !21), !dbg !20
  %5 = shl i32 %2, 16, !dbg !22
  %6 = ashr exact i32 %5, 16, !dbg !22
  %7 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([...] @.str, i64 0, i64 0), i32 %6, i32 %4), !dbg !23
  ret void, !dbg !24
}

[...]
; DISubprogram defines (in our case) a C function, with its full type
!7 = distinct !DISubprogram(name: "print_A", scope: !1, file: !1, line: 6, type: !8, [...], variables: !17)
; This defines the type of our subprogram
!8 = !DISubroutineType(types: !9)
; We have the "original" types used for print_A, with the first one being the
; return type (null => void), and the other ones the arguments (in !10)
!9 = !{null, !10}
!10 = !DIDerivedType(tag: DW_TAG_typedef, name: "A", file: !1, line: 4, baseType: !11)
; This defines our structure, with its various fields
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !1, line: 1, size: 64, elements: !12)
!12 = !{!13, !15}
; We have here the size and name of the member "a". Offset is 0 (default value)
!13 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !11, file: !1, line: 2, baseType: !14, size: 16)
!14 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
; We have here the size, offset and name of the member "b"
!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !11, file: !1, line: 3, baseType: !16, size: 32, offset: 32)
!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
[...]

4、实现

DragonFFI 首先会解析 LLVM IR 里所包含的调试信息,然后创建一个自定义的类型系统,来表示各种各样的函数类型、结构体、枚举、typedef。

之所以创建一个自定义的类型系统,一是因为只需要从元数据树(metadata tree)中获取所需信息就够了(不用所有的调试信息),二是因为可以让 DragonFFI 的公开头文件不需要依赖 LLVM 的头文件。

依赖于 Clang,减少了大量的工作(函数重定义、类型错误、函数对外不可见、类型的内存布局等)。

参考

DragonFFI:https://github.com/aguinet/dragonffi

libffi:https://sourceware.org/libffi/

cffi:https://cffi.readthedocs.io/en/latest/

DWARF:http://dwarfstd.org/

PDB:https://llvm.org/docs/PDB/index.html

DragonFFI: FFI/JIT for the C language using Clang/LLVM:https://blog.llvm.org/2018/03/dragonffi-ffijit-for-c-language-using.html

Skip the FFI!:https://llvm.org/devmtg/2014-10/Slides/Skip%20the%20FFI.pdf

Guinet-DragonFFI:https://llvm.org/devmtg/2018-04

dragonffi:C外函数接口和使用ClangLLVM的JIT 标志由 龙FFI DragonFFI是一个用C ++编写并基于Clang / LLVM的C外函数接口(FFI)库。 它允许任何语言通过提供的API和绑定来调用C函数。 如有任何问题/评论,请随时加入! 目前,仅提供python绑定和C ++ API。 请注意,该项目仍处于Alpha阶段。 文档远未完成,尽管付出了很多努力,但它的API尚未被认为是稳定的! 受支持的OS /体系结构,已 : Linux i386 / x64,具有针对Python 2/3的绑定 Linux / AArch64。 与Python 3绑定 OSX x64,具有针对Python 2/3的绑定 Windows x64,具有适用于Python 3的绑定 为什么要另外一个FFI? 是一个著名的库,为C语言提供FFI。 是围绕此库的python绑定,该绑定也使用pycparser来轻松声明接口和类型。 li 立即下载

相关推荐

gRPC实现跨语言调用–node.js/go(二)

使用node.js语言编写Client,然后向使用go语言编写的server发送RPC请求 安装依赖 cnpm i grpc cnpm install --save grpc-tools 编写Node.js版Client(无编译成js文件) var grpc = require('grpc'); //加载之前编写好的proto文件 var protoDescriptor = grpc.load(__direname+/pb/helloworld.proto); var pb = protoDescriptor.pb;//pb为proto文件的包名 function getClient()

c++ 隐藏进程_深入考察解释型语言背后隐藏的攻击面,Part 2(三)

在本文中,我们将深入地探讨,在通过外部函数接口(Foreign Function Interface,FFI)将基于C/C++的库“粘合”到解释语言的过程中,安全漏洞是如何产生的。深入考察解释型语言背后隐藏的攻击面,Part 2(一)深入考察解释型语言背后隐藏的攻击面,Part 2(二)决定最终的漏洞利用策略为了弄清楚如何在触发我们的堆内存覆盖之前对data_数组进行最佳定位,我们需要检...

weixin_39815435的博客 214

防止加入域主机脱离域的控制(管理员权限)

一、简介   当公司所有主机加入到域后,SA首要工作就是防止加入域的主机脱离域的控制。让我发现该工作的必要性是一程序猿,前一天刚配完禁止执行QQ、微信执行,第二天就看到那家伙在用微信聊天,肯定是用回旧的本地账号登陆了。   本人所在公司安装软件的类型繁杂,无管理员权限运行不少软件会报错,不得不授予「域账号」本地管理员权限。过大的权限带也来了一系列后果:用户可随意退出域、创建本地管理员...

der69615的博客 3174

深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

第五章、JNI机制4.1 JNI概述 由前面基础知识可知,Android的应用层由Java语言编写,Framework框架层则是由Java代码与C/C++语言实现,之所以由两种不同的语言组合开发框架层,是因为Java代码是与硬件环境彻底“隔离”的跨平台语言,Java代码无法直接操作硬件。比如:Android系统支持大量传感器,Java运行在虚拟机中,无法直接得到传感器数据,而Android系统基于

mr_raptor的专栏 1万+

国际项目投标那些事(三)海外项目招标文件的组成

以一个实际的项目作为例子,是我2020年初投的一个东南亚国家的水厂的竞争性投标。这个投标的招标基于FIDIC yellow book (Design and Build) 合同模板。 海外项目的招标一般是有专门的咨询公司(consulting engineer)写招标文件,有的咨询公司非常专业,对于技术、合同、业绩的要求非常细致。 我这个项目的招标文件共5册 400多页(全英文),附件26册将...

WTSolutions的博客 2004

配置xen上VM混杂模式,使其能捕获物理网络流量

本文目的:配置VM和xen相应的物理网卡(pif)和虚拟网卡(vi

LeoDuo的专栏 3720

不同编程语言的程序可不可以通过接口相互调用?一些库为啥可以提供不同语言的接口?

不同编程语言的程序经常互相调用 编程语言之间的直接调用称为互操作,他们之间的接口叫做 Foreign Function Interface。在Linux 平台上,互操作性最好的语言应该是C,因为有比较统一的ABI(应用二进制接口),所以很多语言都会有与C 语言进行互操作的接口,例如解释性语言 CPython 可以利用 python c 扩展,Java 有 Java Native Interface,编译性语言 Rust 通过FFI与 C 进行互操作。根据你说的微处理器的话,如果可以运行操作系统的话,可以利.

qq_41854911的博客 6521

AI小智语音服务架构与嵌入式成本优化实践

语音交互系统是智能硬件的核心能力,其本质是端云协同的实时数据处理链路,涵盖音频采集、流式传输、语义理解与语音合成四大技术环节。原理上需严格划分物理层(确定性音频I/O)、协议层(WebSocket/Range可靠性通信)和语义层(ASR/LLM/TTS职责解耦),以保障低延迟与高可用。技术价值在于通过VAD前置过滤、分块下载、Token截断等嵌入式级优化,显著降低云端调用成本与网络开销。典型应用场景包括儿童故事机、智能音箱、教育机器人等对响应速度、音色自然度和单次交互成本敏感的AI小智设备。本文聚焦火山引擎

weixin_30653091的博客 352

Java 跨语言实现方案

背景: 在大型分布式 java 应用中,为了方便开发者,通常底层的 rpc 框架都会做一些调用的封装,让应用层开发人员在开发服务的时候只用编写简单的 pojo 对象就可以了,如流行的 spring remoting , jboss remoting 等等,都有这样的效果。 随着业务的需要,可能上层应用希望采用非 java 技术,如 php , ruby on rails ,而由于 java g...

weixin_33842328的博客 262

永磁同步电机定子槽型设计实战:从梨形槽到矩形槽的NVH优化之路

本文深入探讨了永磁同步电机定子槽型设计在NVH优化中的关键作用,对比了梨形槽与矩形槽的性能差异。通过Ansys Maxwell仿真和实际案例,揭示了矩形槽在提升槽满率、降低电磁噪声方面的优势,并总结了五大设计黄金法则,为电机设计工程师提供了实用指导。

weixin_28740299的博客 494

CloudCompare 二次开发(17)——点云添加均匀分布的随机噪声

使用CloudCompare编程实现点云添加随机噪声。

点云侠的博客 840

跨语言通信技术选择

最近做一个项目,涉及到多个遗留系统的集成,有c, c++的系统,也有java的系统,所以出现了跨语言通信的问题。通信接口不是很复杂,所以可以使用的技术如下: Socket: 传统的方法,坏处是要考虑很多通信异常情况。 Hessian: 常用的Java HTTP通信框架,但要集成Web Server,而且c, c++的客户端包不太成熟,不同语言的数据类型映射也可能存在问题。 Restful...

iyoungandican的博客 323

10.2 全栈 CRUD 工程结构搭建:Cursor 4 步初始化 + 3 层目录规范

揭示 Cursor 工程初始化中 4 个关键动作如何将 AI 上下文感知能力从 30% 提升至 85%,包括用 pnpm create 显式声明结构契约、通过 monorepo.config.json 设定 workspace 根以支持跨包类型引用、在 shared 包中固化共享类型与协议,以及后续

weixin_42545292的博客 67

DragonFFI 项目推荐

DragonFFI 项目推荐 项目基础介绍和主要编程语言 DragonFFI 是一个基于 Clang/LLVM 的 C 语言外部函数接口(FFI)库,使用 C++ 编写。它旨在为其他编程语言提供调用 C 函数的能力,通过提供的 API 和绑定实现跨语言的函数调用。 项目核心功能 C 语言外部函数接口:DragonFFI 允许任何编程语言通过其提供的 API 和绑定调用 C 函数,实现跨语言的函数...

gitblog_00700的博客 303

YOLO11全网首发:CVPR2026 Transformer注意力 | BinaryAttention 1-bit注意力,推理提速100%,超越FlashAttention2

本文改进:BinaryAttention 结合YOLO11的C3k2模块,全网首发创新。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 855

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【亲测免费】 探索Drogon:高效C++ Web应用框架

**Drogon** 是一款基于C++17/20的HTTP应用框架,旨在通过C++轻松构建各种类型的Web应用服务器程序。Drogon不仅是一个框架,它还是一个强大的工具,能够帮助开发者快速实现高性能、高并发的网络应用。Drogon的名字来源于美国电视剧《权力的游戏》中的一条龙,象征着力量与速度。 ## 项目技术分析 Drogon框架的核心优势在于其非阻塞I/O网络库,该库基于epoll(ma...

gitblog_00732的博客 614

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

跨语言的复杂参数类型传递

hongxiaomeng的博客 1990

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

thrift的使用:(Java、Python之间跨语言调用)

由于公司现在的开发业务模块中,有使用到Java作为客户端调用python服务器端业务处理,因此在底下研究了下,结合了网上的优质文章,在此做一下记录。 thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在C++,Java,Go,Python,PHP,Ruby,Erlang,Perl,C#,Cocoa,JavaScript,Node.js,Smalltalk,and OCaml这些变成语言间无缝结合的。高效的服务。 thrift最初由facebo

BlackMoon 1596

项目实战之跨语言调用api——结合语言优点解决实际问题

项目开发中不同语言间的相互配合

Ccc67ol的博客 1328

跨语言调用

如果使用C和C++去调用是将Swift函数使用闭包接收,然后在桥接文件中extern,然后就可以在C和C++中调用;注:本文不考虑有使用第三方库的方法,所以未包含与JS、Dart等互相调用的情况,后续会持续更新。若要使用C和C++去调用需要在.mm文件中使用对应的方法包装,不能够直接调用。Swift不能直接调用C++代码,可以直接调用C代码,首先在桥接文件中导入。使用@objcMembers修饰的swift类可以被OC使用。不需要桥接,可以直接调用。

Kevin写代码 1022

SQLAlchemy数据库加密:敏感字段存储安全方案终极指南

在当今数据安全至关重要的时代,数据库加密已成为保护敏感信息的必备措施。SQLAlchemy作为Python生态系统中最强大的数据库工具包,提供了多种灵活的加密解决方案来确保你的数据安全。无论你是处理用户密码、个人身份信息还是商业机密,本指南将为你展示如何利用SQLAlchemy实现数据库级别的安全保护。 ## 🔒 为什么需要数据库加密? 数据泄露事件频发,数据库加密不再只是可选项,而是**安

gitblog_00429的博客 480

Foreign function interface (FFI)

FFI说的是一个语言提供的使用其他语言现有库(以及其他组件)的接口。典型的例子包括C++的extern “C”、Java的JNI、.Net的P/Invoke、Python的Python/C API等。 对于新的语言,提供FFI机制是很有现实意义的。提供这样的接口,意味着可以复用已有的无数现有库,而不需要每次都从地板开始构建。对于大多数新的语言,至少要提供的,就是从这种语言到C的一个接口...

a923304245的博客 440

Foreign function interface

<br />http://en.wikipedia.org/wiki/Foreign_function_interface<br /> <br />http://sourceware.org/libffi/

Rare's Tech-Blog 895

FFI (语言交互接口(Foreign Function Interface))

FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java Native Interface) 或 JNA(Java Native Access)。 由于现实中很多程序是由不同编程语言写的,必然会涉及到跨语言调用,比如 A 语言写的函数...

diaoju3333的博客 1802

Python调用其他语言方法:跨语言编程的全方位指南

跨语言编程是指在同一项目中使用多种编程语言进行开发的过程。这有助于充分利用不同语言的优势,提高开发效率和软件质量。本文从Python调用其他语言方法的基础知识出发,详细介绍了跨语言编程的基本概念、常用库、实战案例及注意事项。通过学习本文,读者应该能够全面掌握Python跨语言编程的基本原理和实践技巧,为在不同编程语言之间进行交互提供有力支持。在实际应用中,我们需要根据具体情况选择合适的Python调用其他语言方法技术和策略,以达到高效、稳定地处理数据的目的。

极客代码 2654

使用Thrift实现跨语言RPC调用

前面我们在Thrift入门里面实现了Thrift实现RPC调用的简单案例,而Thrift最大的优势就是可以实现跨语言RPC调用,尤其在一些大厂,微服务各模块之间使用不同的语言是很常见的,有用java的,有go的,有python的,因此,选用Thrift实现RPC远程调用是很不错的选择,本节将在 RPC 框架之Thrift入门(一)的案例基础上,使用java作为服务端,用pytho

阿牛的博客 1765
上一篇: 【译】LLVM 类型系统
下一篇: 代码 bug 嗅探器:Sanitizer
流左沙
博客等级 码龄11年 46粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值