alef 0.62.5

Opinionated polyglot binding generator for Rust libraries
Documentation
// {{ helper_name }} calls the FFI function with visitor support.
func {{ helper_name }}({{ helper_params }}) (*{{ result_type }}, error) {
{{ helper_setup }}

	var cOptions C.{{ conversion_options_type }}
	if {{ options_var }} != nil {
		optionsBytes, err := json.Marshal({{ options_var }})
		if err != nil {
			return nil, fmt.Errorf("failed to marshal options: %w", err)
		}
		optionsJSON := C.CString(string(optionsBytes))
		defer C.free(unsafe.Pointer(optionsJSON))
		cOptions = C.{{ fn_options_from_json }}(optionsJSON)
		if cOptions == 0 {
			if err := lastError(); err != nil {
				return nil, err
			}
			return nil, fmt.Errorf("failed to decode {{ options_type }}")
		}
		defer C.{{ fn_options_free }}(cOptions)
	}
	if cOptions == 0 {
		defaultJSON := C.CString("{}")
		cOptions = C.{{ fn_options_from_json }}(defaultJSON)
		C.free(unsafe.Pointer(defaultJSON))
		if cOptions == 0 {
			if err := lastError(); err != nil {
				return nil, err
			}
			return nil, fmt.Errorf("failed to create default {{ options_type }}")
		}
		defer C.{{ fn_options_free }}(cOptions)
	}

	id := registerVisitor(visitor)
	defer unregisterVisitor(id)
	cb := C.makeVisitorCallbacks(unsafe.Pointer(id))

	visitorHandle := C.{{ fn_visitor_create }}(&cb)
	if visitorHandle == 0 {
		return nil, fmt.Errorf("failed to create visitor handle")
	}

	C.{{ fn_options_set_visitor }}(cOptions, visitorHandle)
	ptr := C.{{ fn_convert }}({{ helper_call_args }})
	if ptr == 0 {
		if err := lastError(); err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("conversion returned nil")
	}
	defer C.{{ fn_result_free }}(ptr)

	jsonPtr := C.{{ fn_result_to_json }}(ptr)
	if jsonPtr == nil {
		return nil, fmt.Errorf("conversion result serialisation failed")
	}
	defer C.free(unsafe.Pointer(jsonPtr))

	var result {{ result_type }}
	if err := json.Unmarshal([]byte(C.GoString(jsonPtr)), &result); err != nil {
		return nil, fmt.Errorf("failed to decode {{ result_type }}: %w", err)
	}
	return &result, nil
}