// NewArrayType creates a new ffi_type with the given size and element type. func NewArrayType(sz int, elmt Type) (Type, error) { n := fmt.Sprintf("%s[%d]", elmt.Name(), sz) if t := TypeByName(n); t != nil { return t, nil } c := C.ffi_type{} t := &cffi_array{ cffi_type: cffi_type{n: n, c: &c}, len: sz, elem: elmt, } t.cffi_type.c.size = C.size_t(sz * int(elmt.Size())) t.cffi_type.c.alignment = C_pointer.c.alignment var c_fields **C.ffi_type = nil C._go_ffi_type_set_elements(t.cptr(), unsafe.Pointer(c_fields)) C._go_ffi_type_set_type(t.cptr(), C.FFI_TYPE_POINTER) // initialize type (computes alignment and size) _, err := NewCif(DefaultAbi, t, nil) if err != nil { return nil, err } register_type(t) return t, nil }
// NewPointerType creates a new ffi_type with the given element type func NewPointerType(elmt Type) (Type, error) { n := elmt.Name() + "*" if t := TypeByName(n); t != nil { return t, nil } c := C.ffi_type{} t := &cffi_ptr{ cffi_type: cffi_type{n: n, c: &c}, elem: elmt, } if elmt.GoType() != nil { t.cffi_type.rt = reflect.PtrTo(elmt.GoType()) } t.cffi_type.c.size = C_pointer.c.size t.cffi_type.c.alignment = C_pointer.c.alignment var c_fields **C.ffi_type = nil C._go_ffi_type_set_elements(t.cptr(), unsafe.Pointer(c_fields)) C._go_ffi_type_set_type(t.cptr(), C.FFI_TYPE_POINTER) // initialize type (computes alignment and size) _, err := NewCif(DefaultAbi, t, nil) if err != nil { return nil, err } register_type(t) return t, nil }
// NewSliceType creates a new ffi_type slice with the given element type func NewSliceType(elmt Type) (Type, error) { n := elmt.Name() + "[]" if t := TypeByName(n); t != nil { return t, nil } c := C.ffi_type{} t := &cffi_slice{ cffi_type: cffi_type{n: n, c: &c}, elem: elmt, } t.cffi_type.c.size = 0 t.cffi_type.c.alignment = 0 C._go_ffi_type_set_type(t.cptr(), C.FFI_TYPE_STRUCT) var c_fields **C.ffi_type = nil var cargs = make([]*C.ffi_type, 3+1) cargs[0] = C_pointer.cptr() // ptr to C-array csize := unsafe.Sizeof(reflect.SliceHeader{}.Cap) if csize == 8 { // Go 1.1 spec allows (but doesn't force) sizeof(int) == 8 cargs[1] = C_int64.cptr() // len cargs[2] = C_int64.cptr() // cap } else { cargs[1] = C_int.cptr() // len cargs[2] = C_int.cptr() // cap } cargs[3] = nil c_fields = &cargs[0] C._go_ffi_type_set_elements(t.cptr(), unsafe.Pointer(c_fields)) // initialize type (computes alignment and size) _, err := NewCif(DefaultAbi, t, nil) if err != nil { return nil, err } register_type(t) return t, nil }
// NewStructType creates a new ffi_type describing a C-struct func NewStructType(name string, fields []Field) (Type, error) { if name == "" { // anonymous type... // generate some id. name = fmt.Sprintf("_ffi_anon_type_%d", <-g_id_ch) } if t := TypeByName(name); t != nil { // check the definitions are the same if t.NumField() != len(fields) { return nil, fmt.Errorf("ffi.NewStructType: inconsistent re-declaration of [%s]", name) } for i := range fields { if fields[i].Name != t.Field(i).Name { return nil, fmt.Errorf("ffi.NewStructType: inconsistent re-declaration of [%s] (field #%d name mismatch)", name, i) } if fields[i].Type != t.Field(i).Type { return nil, fmt.Errorf("ffi.NewStructType: inconsistent re-declaration of [%s] (field #%d type mismatch)", name, i) } } return t, nil } c := C.ffi_type{} t := &cffi_struct{ cffi_type: cffi_type{n: name, c: &c}, fields: make([]StructField, len(fields)), } t.cffi_type.c.size = 0 t.cffi_type.c.alignment = 0 C._go_ffi_type_set_type(t.cptr(), C.FFI_TYPE_STRUCT) var c_fields **C.ffi_type = nil if len(fields) > 0 { var cargs = make([]*C.ffi_type, len(fields)+1) for i, f := range fields { cargs[i] = f.Type.cptr() } cargs[len(fields)] = nil c_fields = &cargs[0] } C._go_ffi_type_set_elements(t.cptr(), unsafe.Pointer(c_fields)) // initialize type (computes alignment and size) _, err := NewCif(DefaultAbi, t, nil) if err != nil { return nil, err } for i := 0; i < len(fields); i++ { //cft := C._go_ffi_type_get_element(t.cptr(), C.int(i)) ff := fields[i] t.fields[i] = StructField{ ff.Name, TypeByName(ff.Type.Name()), uintptr(C._go_ffi_type_get_offsetof(t.cptr(), C.int(i))), } } register_type(t) return t, nil }