Android Question Program does not work after migrating from B4A 9.80 to 10.70

Losapiens

New Member
Hello
last year I wrote a class (in B4A 9.80) that uses UDPSocket and resumable subs to learn B4X starting from my needs. I installed B4A 10.70 in a new VM and found that with the new version it doesn't work (with the old it still works).

B4A:
Private Sub WaitForMessageHelper (Result() As Object) As ResumableSub
    Wait For UDP_PacketArrived (Packet As UDPPacket)
    Result(0) = Packet
    Return Null
End Sub

Private Sub SendSync(send As UDPPacket, recv As UDPPacket) As ResumableSub
    
    Dim rs As ResumableSub
    Dim result(1) As Object
    Dim timer As Int = 0

    Socket.Send(send)

    rs = WaitForMessageHelper(result)
    
    Do While mTimeout > timer And rs.Completed = False
        Sleep(50)
        timer = timer + 50
    Loop
    If rs.Completed Then
        recv = result(0)
        'check the response
        Log($"Receceived ${recv.Length} bytes from: ${recv.HostAddress}:${recv.Port} after ${timer}ms"$)
        Return True
    Else
        Log("Timeout reached!")
        Return False
    End If

End Sub
The log states that the answer arrives, but outside the call recv is not initialized:
B4A: SendSync call - result is true:
Wait For (SendSync(Packet_send, Packet_recv)) Complete (result As Boolean)
If result = True Then
    If Packet_recv.IsInitialized Then
        'do stuff'
        Return True
    Else
        'error'
        Return False
    End If
End If
If it can help, digging into the generated java sources I found that the only difference between the two versions is the following:
Java: SendSync line 22:
 //BA.debugLine="recv = result(0)";

//version 9.80
_recv.setObject((anywheresoftware.b4a.objects.SocketWrapper.UDPSocket.MyDatagramPacket)(_result[(int) (0)]));

//version 10.70
_recv = (anywheresoftware.b4a.objects.SocketWrapper.UDPSocket.UDPPacket) anywheresoftware.b4a.AbsObjectWrapper.ConvertToWrapper(new anywheresoftware.b4a.objects.SocketWrapper.UDPSocket.UDPPacket(), (anywheresoftware.b4a.objects.SocketWrapper.UDPSocket.MyDatagramPacket)(_result[(int) (0)]));

Where am I wrong?
Thanks for your help
 

Losapiens

New Member
B4X:
Wait For (SendSync(Packet_send, Packet_recv)) Complete (result As Boolean)
Log("After SendSync: " & result & " - " & Packet_recv.IsInitialized)
This code instead produces this log (in v10.70 only)
Log:
Receceived 21 bytes from: <192.168.0.170:12000> after 50ms
After SendSync: true - false
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Now I understand. Your code worked because of a bug in older versions of B4A.

B4X:
SendSync(..., Packet)

Private Sub SendSync(send As UDPPacket, recv As UDPPacket) As ResumableSub
   recv = result(0)  '<-----
This assignment should never affect Packet. The local variable just points to a different object now.

There are all kinds of ways to pass back the result.
One simple way:
B4X:
Wait For (SendSync(Packet_send, Packet_recv)) Complete (result() As Object)
If result(0) = True Then
  Dim p As UDPPacket = result(1)


Private Sub SendSync(send As UDPPacket, recv As UDPPacket) As ResumableSub
 Return Array(Success, recv)
End Sub
 
Upvote 0

Losapiens

New Member
Now I see it too: pass-by-value is the answer.
Your solution obviously works!

Now I will focus on ways of passing values back, to improve the function signature.

Thank you, @Erel
 
Upvote 0
Top