NordSecurity / uniffi-bindgen-go

Uniffi bindings generator for Golang
Mozilla Public License 2.0
65 stars 18 forks source link

How to use Callbacks? #35

Closed iBims1JFK closed 6 months ago

iBims1JFK commented 7 months ago

Hello, this is a follow up issue to #32 after upgrading uniffi-rs to 0.25.2 it was possible to generate the correct bindings and to build and link the binary as well. Now we are stuck at the next problem, which is how to use callbacks. I would like to call PackPlaintext which is autogenerated by uniffi-go.

func (_self *DidComm) PackPlaintext(msg Message, cb OnPackPlaintextResult) ErrorCode {
    _pointer := _self.ffiObject.incrementPointer("*DidComm")
    defer _self.ffiObject.decrementPointer()
    return FfiConverterTypeErrorCodeINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI {
        return C.uniffi_didcomm_uniffi_fn_method_didcomm_pack_plaintext(
            _pointer, FfiConverterTypeMessageINSTANCE.Lower(msg), FfiConverterCallbackInterfaceOnPackPlaintextResultINSTANCE.Lower(cb), _uniffiStatus)
    }))
}
type OnPackPlaintextResult interface {
    Success(result string)
    Error(err *ErrorKind, msg string)
}

Therefore I need to implement the OnPackPlaintextResult Interface

type MyPackPlaintextResult struct{}

func (m *MyPackPlaintextResult) Success(result string) {
    fmt.Println("PackPlaintext succeeded:", result)
}

func (m *MyPackPlaintextResult) Error(err *didcomm.ErrorKind, msg string) {
    fmt.Println("PackPlaintext failed:", err, msg)
}

When calling now the PackPlaintext function, none of the print statements is executed. I also tried to pass pointer to the MyPackPlaintextResult but it did not make any difference. Is this expected behavior or do I need to do something differently?

The documentation suggests a similar way. This is the implementation of the library.

code.zip

arg0d commented 7 months ago

I tried to generate bindings using uniffi-bindgen-go 0.2.0+v0.25.0 for didcomm.udl and the generated bindings don't compile with Go 1.20 at line 3134. I kind of understand the problem, and will try to look into this. Which exact UDL file are you using? Which didcomm commit?

MrMaavin commented 7 months ago

I tried to generate bindings using uniffi-bindgen-go 0.2.0+v0.25.0 for didcomm.udl and the generated bindings don't compile with Go 1.20 at line 3134. I kind of understand the problem, and will try to look into this. Which exact UDL file are you using? Which didcomm commit?

We used the UDL you mentioned and the lastest commit of didcomm-rust (main branch). We had to adjust some functions in the generated bindings so that it compiles. Here are the adjusted go bindings so that it compiles: go-bindings.zip

iBims1JFK commented 7 months ago

I think that we are using this fork where also the unffi version upgrade implemented is.

I have adjusted the bindings so that the error is handled like this. For example

func (foreignCallbackCallbackInterfaceOnFromPriorPackResult) InvokeError(callback OnFromPriorPackResult, args []byte, outBuf *C.RustBuffer) uniffiCallbackResult {
    reader := bytes.NewReader(args)
    err := FfiConverterTypeErrorKindINSTANCE.Read(reader)

    // Type assertion to convert err to *ErrorKind
    if errKind, ok := err.(*ErrorKind); ok {
        callback.Error(errKind, FfiConverterStringINSTANCE.Read(reader))
    } else {
        // Handle the case where the error is not of type *ErrorKind
        // You may want to log an error or handle it appropriately.
    }

    return uniffiCallbackResultSuccess
}

I hope that this is the line that you are referring to

arg0d commented 7 months ago

The Rust code implementation you provided is asynchronuous, and Rust code does not execute the callback in time before the program closes. Adding time.Sleep(1 * time.Second) at the end of main gives enough time for callback to execute.