跨语言调 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

基于STM32F407与AD9910/AD9959的高频可调DDS信号源设计与实战

本文详细介绍了基于STM32F407微控制器与AD9910/AD9959高性能DDS芯片的高频可调信号源设计与实现。文章从DDS原理入手,阐述了双芯片方案的优势,并重点分享了高频电路设计中的电源、PCB布局布线等关键硬件设计技巧与避坑指南。同时,提供了通过SPI配置DDS芯片及利用Matlab生成任意波形的软件驱动方法,旨在帮助开发者打造一个覆盖10Hz至4200MHz的实用信号发生器。

weixin_36184718的博客 122

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

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

mr_raptor的专栏 1万+

实战游戏项目管理1-规划篇

1、前言 做研发管理10多年,进游戏行业8年,经验下来项目管理就是一门技术,结合不同行业不同项目加以不同管理方法,但原理基本一样,这里总结下游戏项目的管理一些实操方法 一般游戏确定立项前都需要做,项目预研产出一个游戏Demo,通过公司的立项评审,这个过程的项目管理相对简单一般由制作人或其他项目经理兼任,只有控制好总体时间与成本就好,这里按立项后开始讲。 2、游戏项目规划 ...

pengdali的专栏 2万+

win10自动修复-无限循环【通用完美】超简单解决办法

2020.02.14今个我的笔记本电脑(Thinkpad Carbon 7 X1)(win10)早晨起来发现蓝屏,上面显示自动修复失败,重启后依然自动修复失败,不断手动重启,始终是修复失败。然后上网开始搜集资料找解决办法。 前边介绍关闭自动修复,如何找出错文件的方法;如果想看最终解决办法,直接看第三部分 上网就会发现这种现象很常见,同时是电脑自动安装系统更新,或者安装某些驱动出现。解决办法也大...

y15941300574的博客 19万+

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

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

qq_41854911的博客 6521

《湖科大教书匠计算机网络》学习笔记总目录+思维导图

本篇文章是对《湖科大教书匠计算机网络》所有知识点的笔记总结归档和计算机网络的思维导图

weixin_73077810的博客 8252

Java 跨语言实现方案

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

weixin_33842328的博客 262

Field-Oriented Control (FOC) 矢量控制 磁场定向控制

Field-Oriented Control (FOC) 磁场定向控制(FOC),也称为矢量控制,是一种用于控制永磁同步电动机(PMSM)和交流感应电动机(ACIM)的技术。 FOC在整个扭矩和速度范围内都具有良好的控制能力。 FOC的实现需要将定子电流从固定参考系转换为转子磁通参考系(也称为d-q参考系)。 速度控制和转矩控制是FOC最常用的控制模式。位置控制模式不太常见。大多数牵引应用使用转矩控制模式,在该模式下,电动机控制系统遵循参考转矩值。在速度控制模式下,电机控制器遵循参考速度值,并生成用于形成内

>>> 1万+

FDTD仿真进阶:液晶偏振调控与双折射效应全解析

本文深入解析了在Lumerical FDTD仿真中如何对液晶材料进行偏振调控与双折射效应建模。通过单轴液晶和螺旋扭曲液晶(TN-LCD)两大实战案例,详细阐述了从各向异性材料参数设置、LC网格属性配置到偏振椭圆分析的全流程,帮助工程师精准模拟液晶的光开关行为,优化如显示器等器件的光学性能。

chair的专栏 746

跨语言通信技术选择

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

iyoungandican的博客 323

【EMC电磁兼容】02.04——原理图的实战落地细节

原理图上的关于EMC的落地体现一、元器件的选型二、原理图上的EMC体现在哪里?1.芯片电源管脚滤波去耦:2.时钟电路滤波设计3.低速电路滤波抗干扰设计4.通讯接口电路的防护滤波5.系统输入电源端口电路的防护滤波6.系统接地的定义7.芯片软件功能的审查 一、元器件的选型 ​ 原理图最初设计涉及到选型元器件方面: 元器件选型 不仅仅功能需要满足要求,还需要考虑其它细节参数在不同应力下的反应,封装的不同也会产生不同的变化。 元器件替代 常常因为成本原因进行器件替代,除了要考虑功能参数相同时也要考虑系统参数

Time to Forget 2246

DragonFFI 项目推荐

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

gitblog_00700的博客 303

基于YOLOv8的植物生长阶段识别系统设计与实现

本文详细介绍了一个基于YOLOv8深度学习模型的植物生长阶段识别系统,包含完整的数据集构建、模型训练、评估以及基于PyQt5的用户界面开发过程。系统能够自动识别植物在不同生长阶段(如发芽期、生长期、开花期、结果期等)的形态特征,为精准农业和智能种植提供技术支持。文章提供了完整的代码实现,并讨论了模型优化策略和实际应用场景。关键词:植物生长阶段识别、YOLOv8、目标检测、PyQt5、深度学习。

YOLO 466

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

gitblog_00732的博客 614

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

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

hongxiaomeng的博客 1990

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

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、付费专栏及课程。

余额充值