Jump to content
  • Advertisement
Sign in to follow this  
Driv3MeFar

What am I doing wrong (template stupidity)?

This topic is 4428 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there, I've been trying to get sending working in my game for the last hour or two with no luck. I have templatized send functions for both my client and server, because they can send multiple types of messages. At first I was getting linker errors when calling the send() functions, but then I explicity instantiated them at the bottom of my networking header file. Since doing that, my linker errors have been replaced with INTERNAL COMPILER ERRORs. I'm stumped, so I turn to you, GDnet. Code (implicit instantiations, INTERNAL COMILER ERRORs): NObject.h:
class CNetClient : public CNetObject
{
public:
...
template <typename T>
bool Send(T &msg);
...
};

class CNetServer : public CNetObject
{
public:
...
	template <typename T>
	bool Send(T &msg);  //send msg to all clients
...
};

//Explicit Instantiations of my send() functions
template bool CNetClient::Send<stNetChatMessage>(stNetChatMessage&);
template bool CNetClient::Send<stNetGameMessage>(stNetGameMessage&);
template bool CNetServer::Send<stNetChatMessage>(stNetChatMessage&);
template bool CNetServer::Send<stNetGameMessage>(stNetGameMessage&);

NObject.cpp:
template <typename T>
bool CNetClient::Send(T &msg)
{
	int bufSize = sizeof( T ) * (MAXQUEUESIZE + 1) + 1;
	char buf[ sizeof( T ) * (MAXQUEUESIZE + 1) + 1 ];
	ZeroMemory(buf, bufSize);
	memcpy( buf, &msg, sizeof(T) );
	//add queued reliable messages to the outgoing message
	int i = sizeof(T);
	for (std::vector<stNetGameMessage>::iterator it = relMsgQueue.begin(); it != relMsgQueue.end(); ++it)
	{
		memcpy( buf + i, &(*it), sizeof(stNetGameMessage) );
		i += sizeof(stNetGameMessage);
	}
	buf = -1;
	int err = send( s, buf, bufSize, 0 );
	if (err == SOCKET_ERROR)
	{
		//send should not block, so always return false on error
		return false;
	}
	return true;
}

template <typename T>
bool CNetServer::Send(T &msg)  //send msg to all clients
{
	int bufSize = sizeof( T ) * (MAXQUEUESIZE + 1) + 1;
	char buf[ sizeof( T ) * (MAXQUEUESIZE + 1) + 1 ];
	for (int i = 0; i < 8; ++i)
	{
		if ( clients == NULL )
		{
			continue;
		}
		ZeroMemory(buf, bufSize);
		memcpy( buf, &msg, sizeof(T) );
		//add queued reliable messages to the outgoing message
		int s = sizeof(T);
		for (std::vector<stNetGameMessage>::iterator it = relMsgQueues.begin(); it != relMsgQueues.end(); ++it)
		{
			memcpy( buf + s, &(*it), sizeof(stNetGameMessage) );
			s += sizeof(stNetGameMessage);
		}
		buf[s] = -1;
		send( clients->getSocket() , buf, bufSize, 0 );
	}
	return true;
}

main.cpp:
reinterpret_cast< CNetServer* >(g_NetObj)->Send(*gMsg);
//Error: c:\documents and settings\administrator\desktop\sum260\game\main.cpp(64): fatal error C1001: INTERNAL COMPILER ERROR  (compiler file 'f:\vs70builds\3077\vc\Compiler\Utc\src\P2\main.c', line 148)


When I was getting linker errors, the only difference was that the instantiations were not in NObject.h, and the functions was called: reinterpret_cast< CNetServer* >(g_NetObj)->Send< stNetGameMessage >(*gMsg); Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Driv3MeFar
reinterpret_cast< CNetServer* >(g_NetObj)->Send(*gMsg);


From the first glance this looks kind of wrong. Can you try
(reinterpret_cast< CNetServer* >(g_NetObj))->Send(*gMsg);

or

CNetServer* s = reinterpret_cast< CNetServer* >(g_NetObj);
s->Send(*gMsg);

Internal compiler error means the compiler got totally confused. Sometimes writing it out a different way solves the problem.

Share this post


Link to post
Share on other sites
- Template function definitions must be in the header. Move all the template definitions in NOBject.cpp to NObject.h.

- Remove the "explicit instantiations", they aren't even syntactically correct.

If I may, why didn't you post here with the linker errors instead?

Share this post


Link to post
Share on other sites
Ok, the problem is that the template definitions are in the cpp files, move them into the header files and you should be OK.

Share this post


Link to post
Share on other sites
Quote:
Original post by jflanglois
- Template function definitions must be in the header. Move all the template definitions in NOBject.cpp to NObject.h.

- Remove the "explicit instantiations", they aren't even syntactically correct.

If I may, why didn't you post here with the linker errors instead?


- Thanks, I knew I was forgetting something stupid.

- k (How are they syntactically wrong? I was just going off of MSDN)

And as for the linker errors, because I happened to have my code set up such that it was generating the INTERNAL COMPILER ERRORS, and I didn't particularly feel like changing it around again.

Share this post


Link to post
Share on other sites
While I'm on the subject of templates, I was trying to do this earlier and I realised I had no idea how:
How would you syntactically denote a templatized callback function?
For example, if I wanted my recv() function to take as a paramater a pointer to a templatized function, how could I do it?
Would it be as simple as:
template <typename T>
bool recv( void (*func)(T &msg) ) {}
But then recv() is templatized, and I dont want that, just the callback...
...I confused myself

Share this post


Link to post
Share on other sites
It would look something like this:
template< class T >
void CallBack( T const * const ) {
}

template< class T >
void recv( void ( *Callback )( T const * const ) ) {
Callback( new T() );
}

int main() {
recv( CallBack< int > );
}

It's not very practical, though. I suggest you create a new thread regarding what you are trying to do, so someone can suggest a better aproach.

Share this post


Link to post
Share on other sites
Quote:
Original post by jflanglois
It would look something like this:
template< class T >
void CallBack( T const * const ) {
}

template< class T >
void recv( void ( *Callback )( T const * const ) ) {
Callback( new T() );
}

int main() {
recv( CallBack< int > );
}

It's not very practical, though. I suggest you create a new thread regarding what you are trying to do, so someone can suggest a better aproach.


Interesting, thanks. I already have a different way of doing it for my game, I was just curious, really.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!