https://github.com/aguinet/dragonffi
 
FOSDEM 2018 - Adrien Guinet (@adriengnt)
2018/02/04
import pydffi
CU = pydffi.FFI().cdef("int puts(const char* s);");
CU.funcs.puts("hello world!")
C functions are usually called from "higher" level languages for performances...
ffi_cif cif;
ffi_type *args[] = {&ffi_type_pointer};
void* values[] = &s;
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_sint, args);
s = "Hello World!";
ffi_call(&cif, puts, &rc, values);
cffi.FFI().cdef("#include
") CDefError: cannot parse "#include " :2: Directives not supported yet cffi.FFI().cdef("__attribute__((ms_abi)) int foo(int a, int b) { return a+b; }") CDefError: cannot parse "__attribute__((ms_abi)) int foo(int a, int b) { return a+b; }" :2:15: before: (
But that wouldn't be that easy right...? :)
typedef struct {
short a;
int b;
} A;
void print_A(A s) {
printf("%d %d\n", s.a, s.b);
}
$ clang -Xclang -ast-dump a.c
-RecordDecl 0x[..] line:2:9 struct definition
| |-FieldDecl 0x[..] col:9 referenced a 'short'
| `-FieldDecl 0x[..] col:7 referenced b 'int'
typedef struct {
short a;
int b;
} A;
void print_A(A s) {
printf("%d %d\n", s.a, s.b);
}
$ clang -S -emit-llvm -o - a.c
[..]
target triple = "x86_64-pc-linux-gnu"
@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
define void @print_A(i64) local_unnamed_addr #0 {
...
}
typedef struct {
short a;
int b;
} A;
void print_A(A s) {
printf("%d %d\n", s.a, s.b);
}
$ clang -S -emit-llvm -o - -m32 a.c
target triple = "i386-pc-linux-gnu"
%struct.A = type { i16, i32 }
@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
; Function Attrs: nounwind
define void @print_A(%struct.A* byval nocapture readonly align 4) local_unnamed_addr #0 {
...
}
typedef struct {
short a;
int b;
} A;
void print_A(A s) {
printf("%d %d\n", s.a, s.b);
}
$ clang -S -emit-llvm -o - -m32 a.c -g
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, size: 64, elements: !12)
!12 = !{!13, !15}
!13 = !DIDerivedType(tag: DW_TAG_member, name: "a", baseType: !14, size: 16)
!14 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", baseType: !16, size: 32, offset: 32)
!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
DWARF metadata are parsed to create DFFI types:
Every type can be const-qualified!
// For this function declaration
int puts(const char* s);
// We generate this wrapper
void __dffi_wrapper_0(int32_t ( __attribute__((cdecl)) *__FPtr)(char *),
int32_t *__Ret,void** __Args) {
*__Ret = (__FPtr)(*((char **)__Args[0]));
}
Main one
typedef struct {
short a;
int b;
} A;
void print_A(A s);
$ clang -S -emit-llvm -g -femit-all-decls -o - a.c |grep print_A |wc -l
0
https://github.com/aguinet/dragonffi
pip install pydffi
For Linux x86/64 users only
Twitter: @adriengnt
Mail: adrien@guinet.me