The ENet library has packets that can be send, and includes a callback function once it has finished sending that specific packet.
http://enet.bespin.org/structENetPacket.html#ad602d6b6b35ef88b2b2e080fa5c9dc3d
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
void * userData; /**< application private data, may be freely modified */
} ENetPacket;
The callback itself:
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
Now I want to create a class that holds the host used to send those packets, and also to keep track how many packets were successfully sent.
template<typename T>
class Sender {
public:
explicit Sender() { }
void send(T* data, int32_t length)
{
ENetPacket* packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE);
packet->freeCallback = callbackPacket;
enet_host_broadcast(m_server, 0, packet);
}
void callbackPacket(ENetPacket* packet)
{
--m_counter_packets_active;
}
};
This does not compile: Error C3867 Sender<int32_t>::callbackPacket': non-standard syntax; use '&' to create a pointer to member
When I try
packet->freeCallback = &this->callbackPacket;
I get Error C2440 '=': cannot convert from 'void (Sender<int32_t>::* )(ENetPacket *)' to 'ENetPacketFreeCallback'
I just don't understand what the proper code would be for the packet calling the Sender object's method when the packet is done with.
Okay, this is pretty common. First, you can't call a non-static member method this way, not directly. Pain in the ass.
But that callback structure has a userData field. And that's what we're going to use.
void send(T* data, int32_t length) {
ENetPacket* packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE);
packet->freeCallback = &Sender::myStaticMethod;
packet->userData = this; // This is part of the magic
enet_host_broadcast(m_server, 0, packet);
}
static void myStaticMethod(ENetPacket * packet) {
Sender * sender = static_cast<Sender *>(packet->userData);
sender-> callbackPacket(packet);
}
In other words -- store this
as your user data. Use a static method for the callback, and have him turn it around to call your real callback.