B4J Question Cannot convert custom class to object

MathiasM

Active Member
Licensed User
Hello

I'm trying to write a gameserver, the gameserver is using good old TCP sockets for communication.
I have the following structure:
  • A GameServerSocket class, which handles new incomming connections (and players etc)
  • A NetworkClient class, which is a .. Client, A client that is connected, but not authenticated and thus has no relation to any player at all.
  • A Player class, holds player data, and a NetworkClient reference AFTER authentication.
Each class is responsible for some level of network handling. EG: the NetworkClient class only converts the incomming Byte array to a UTF8 string and passes the message on via a callback (CallSub)

The problem that arises here: When a networkclient is "attached" to the player class, it should perform a CallSub to the Player class, which handles player messages, not to the GameServerSocket, which only handles network data from unauthenticated sockets (thus not players). The class to callback to is in other words dynamic.

Basically, when a new socket is connected, I create a NetworkClient in the GameserverSocket class, and pass an Eventname and a Class to callback to (Me)
B4X:
Public Sub server_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        Dim newNetClient As NetworkClient
        newNetClient.Initialize(NewSocket, Me, "UnauthenticatedNetClient")
        mUnauthenticatedNetclientList.Add(newNetClient)
    End If
End Sub

Where the NetworkClient.Initialize code looks like this:
B4X:
Public Sub Initialize( Sock As Socket, ParentToCallback As Object, EventName As String)
    mSocket = Sock
    mParentToCallback = ParentToCallback
    mEventName = EventName
    mStream.InitializePrefix(Sock.InputStream, False, Sock.OutputStream, "stream")
End Sub

Notice that ParentToCallback is an Object in this context, as it could be a GameServerSocket object or a Player object that is needs to be used in the CallSub (if authenticated yes or no)

The Callback is used this way in the NetworkClient Class:
B4X:
Private Sub stream_NewData (Buffer() As Byte)
    Dim msg As String
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
    CallSub3(mParentToCallback, mEventName & "_NewData", Me, msg)
End Sub

But, I get an error when I try to pass "Me" (from the GameServerSocket object) to the Initialize ParentToCallback parameter, stating:
Compiling generated Java code. Error
B4J line: 21
newNetClient.Initialize(NewSocket, Me, \
src\b4j\example\gameserversocket.java:116: error: incompatible types: gameserversocket cannot be converted to object
_newnetclient._initialize /*String*/ (null,ba,_newsocket,(b4j.example.object)(this),"UnauthenticatedNetClient");
^
1 error

GameServerSocket cannot be converted to Object (while my thinking process was: It shouldn't be converted, it should just hold a "lowest common denominator' reference to it, and I was thinking Object was somekind of baseclass for everything.)

What kind of type should I use for unknown class reference to callback to, if not object?
I don't use the object for anything else in this context.

I searched in the Booklets, but there Object is used all the time for Callback purposes, so I don't know why my custom class GameServerSocket cannot be converted to an object?

thanks for any help or insights!
 
Last edited:
Solution
I tried changing the code to this:

B4X:
Dim obj As Object = Me
newNetClient.Initialize(NewSocket, obj, "UnauthenticatedNetClient")

But this also fails on the first line, cannot convert Me to Object. Very odd as Me is an Object by definition (as written in the documentation)

When I comment out the line that causes the error, I get an error somewhere else in my code (in the Player class)
B4X:
Public Sub AttachNetworkClient(NetClient As NetworkClient, EventName As String)
    mEventname = EventName
    mNetworkClient = NetClient
    mNetworkClient.ChangeCallback(Me, "NetClient")
End Sub

The exact same error, so the Player Me instance can also not be cast to an Object type.


Edit: After looking at the code many times I found...

William Lancee

Well-Known Member
Licensed User
Longtime User
Your Initialize has 3 parameters

Public Sub Initialize( Sock As Socket, ParentToCallback As Object, EventName As String)

Your call has 4 parameters

It happens;)
 
Upvote 0

MathiasM

Active Member
Licensed User
Your Initialize has 3 parameters

Public Sub Initialize( Sock As Socket, ParentToCallback As Object, EventName As String)

Your call has 4 parameters

It happens;)
You're right, it was wrong in my post. (I was working on the code while creating this post)

In my real code it only has 3 parameters, and the error is still the same, so it must be unrelated.

Thanks for helping me!
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Are you sure the instance of GameServerSocket is properly initialized?

"Me" is an instance of that class, not the class itself.
Somewhere you need something like

Private XXXX as GameServerSocket
XXXX.Initialize(...)

I can't really test the setup that you have. So others may be better able to help.
 
Upvote 0

MathiasM

Active Member
Licensed User
The error is thrown at compilation, not at runtime, so B4J isn't aware of instances yet. (I think)

The problem is that I cannot recreate the problem with a scaled down version. Simple examples just seem to work as expected..

I attached the project, maybe @Erel can shine a light on this, the problem is I have searched the forum and even stackoverflow with the java error, and I can not find a comparable case. While I still think I'm just being stupid somewhere.
 

Attachments

  • server.zip
    5.7 KB · Views: 212
Upvote 0

MathiasM

Active Member
Licensed User
I tried changing the code to this:

B4X:
Dim obj As Object = Me
newNetClient.Initialize(NewSocket, obj, "UnauthenticatedNetClient")

But this also fails on the first line, cannot convert Me to Object. Very odd as Me is an Object by definition (as written in the documentation)

When I comment out the line that causes the error, I get an error somewhere else in my code (in the Player class)
B4X:
Public Sub AttachNetworkClient(NetClient As NetworkClient, EventName As String)
    mEventname = EventName
    mNetworkClient = NetClient
    mNetworkClient.ChangeCallback(Me, "NetClient")
End Sub

The exact same error, so the Player Me instance can also not be cast to an Object type.


Edit: After looking at the code many times I found the problem. In a fuzzy moment I created an Object class (as in 3D object) which ofcourse caused havoc with the real Object type.

Thanks everybody for the help!
 
Last edited:
Upvote 0
Solution

William Lancee

Well-Known Member
Licensed User
Longtime User
I created an Object class (as in 3D object)

Ah! I know it was natural at the time, and it would stump me too.
I am somewhat surprised that B4X would let you create an "Object" class
Would it also let one create a "String" class or a "Int" class?
 
Upvote 0

MathiasM

Active Member
Licensed User
I am somewhat surprised that B4X would let you create an "Object" class
Would it also let one create a "String" class or a "Int" class?
I was curious too. I tried it and it does let you create it. Both with different behaviour though. Initializing a class named String will compile but throws an exception at runtime. Using a class named Int won't compile at all.

We learn all the time. ?
 
Upvote 0
Top