Ejemplo n.º 1
0
// 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
}
Ejemplo n.º 2
0
// 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
}
Ejemplo n.º 3
0
// 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
}
Ejemplo n.º 4
0
// 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
}