예제 #1
0
파일: ffi.go 프로젝트: beoran/ffidll
func Prepare(fun *Function, nargs uint) (*Callable, int) {
	var cif C.ffi_cif
	var typp *C.ffi_type
	ffi_type_void := ffi_type_for(TYPE_VOID, nil)
	// recover from panic here
	defer func() {
		if x := recover(); x != nil {
			println("panicking with value", x)
		}
		println("function returns normally") // executes only when hideErrors==true
	}()

	call := &Callable{}
	println("cif size: ", unsafe.Sizeof(cif))
	call.cifmem = Allocate(unsafe.Sizeof(cif) + 100)
	call.argimem = Allocate(unsafe.Sizeof(typp) * 10)
	call.cif = &call.cifs

	// (*C.ffi_cif)(call.cifmem.Ptr())
	// fmt.Println("cif ABI, nargs:", int(call.cif.abi), int(call.cif.nargs))
	call.cif.abi = C.FFI_DEFAULT_ABI
	call.cif.nargs = C.uint(nargs)
	call.fun = fun
	call.cif.rtype = &ffi_type_void
	//stat          := 777
	println("cif address:", (unsafe.Pointer)(call.cif))
	println("void type address:", (unsafe.Pointer)(&ffi_type_void))
	println("cgo void type address:", (unsafe.Pointer)(&C.ffi_type_void))

	stat := C.ffi_prep_cif(call.cif, C.FFI_DEFAULT_ABI, C.uint(nargs),
		&ffi_type_void, nil)

	/*&C.ffi_type_void, (**C.ffi_type)(call.argimem.ptr))*/
	return call, int(stat)
}
예제 #2
0
func create_func(f interface{}) *CFn {

	cfn := new(CFn)

	closure := C.ffi_closure_alloc(
		C.size_t(unsafe.Sizeof(C.ffi_closure{})),
		&(cfn.fn_ptr))

	if closure == nil {
		return nil
	}

	cfn.closure = closure

	runtime.SetFinalizer(cfn, free_cfn)

	fn_data := new(FuncData)

	fn_data.fn = reflect.ValueOf(f)
	fn_data.fn_type = fn_data.fn.Type()

	cfn.fn_data = fn_data

	numIn := fn_data.NumIn()

	args := get_args_define(fn_data.InTypes(), numIn)

	var ret_type *C.ffi_type

	numOut := fn_data.NumOut()
	if numOut == 1 {
		ret_type = ffi_type(fn_data.OutTypes()[0])
		// fmt.Println((fn_data.OutTypes()[0]).Kind())
	} else {
		// TODO: please handle numOut > 1
		ret_type = &C.ffi_type_void
	}

	if C.ffi_prep_cif(&(fn_data.cif),
		C.FFI_DEFAULT_ABI,
		C.uint(numIn),
		ret_type,
		args) != C.FFI_OK {
		return nil
	}

	if C.ffi_prep_closure_loc(
		(*C.ffi_closure)(closure),
		&(fn_data.cif),
		(*[0]byte)(C.binding),
		unsafe.Pointer(fn_data),
		cfn.fn_ptr) != C.FFI_OK {
		return nil
	}

	return cfn

}
예제 #3
0
파일: ffi.go 프로젝트: cookieo9/goffi
func NewCIF(abi ABI, rtype Type, atypes ...Type) (CIF, error) {
	var cif C.ffi_cif
	atypes_ptr := (**C.ffi_type)(unsafe.Pointer(&atypes[0]))
	status := C.ffi_prep_cif(&cif, C.ffi_abi(abi), C.uint(len(atypes)), rtype, atypes_ptr)
	if status == C.FFI_OK {
		return CIF(cif), nil
	}
	return CIF{}, ffi_error(status)
}
예제 #4
0
파일: ffi.go 프로젝트: sbinet/go-ffi
// NewCif creates a new ffi call interface object
func NewCif(abi Abi, rtype Type, args []Type) (*Cif, error) {
	cif := &Cif{}
	c_nargs := C.uint(len(args))
	var c_args **C.ffi_type = nil
	if len(args) > 0 {
		var cargs = make([]*C.ffi_type, len(args))
		for i, _ := range args {
			cargs[i] = args[i].cptr()
		}
		c_args = &cargs[0]
	}
	sc := C.ffi_prep_cif(&cif.c, C.ffi_abi(abi), c_nargs, rtype.cptr(), c_args)
	if sc != C.FFI_OK {
		return nil, fmt.Errorf("error while preparing cif (%s)",
			Status(sc))
	}
	cif.rtype = rtype
	cif.args = args
	return cif, nil
}
예제 #5
0
func Prepare(ret Type, args ...Type) (cif Interface) {
	cif.ffi_ret = ret.ffi_type
	cif.ret = ret
	cif.args = args
	argc := len(args)

	if argc != 0 {
		va := make([]*C.ffi_type, argc)

		for i, a := range args {
			va[i] = a.ffi_type
		}

		cif.ffi_args = &va[0]
	}

	if status := Status(C.ffi_prep_cif(&cif.ffi_cif, C.FFI_DEFAULT_ABI, C.uint(argc), cif.ffi_ret, cif.ffi_args)); status != OK {
		panic(status)
	}

	return
}