Reputation: 1460
I am trying to use Solace c API through C++ classes.
There is already framework created in the existing project with reference to Base and Derived class, where derived virtual functions are called accordingly to the object referenced as run time.
My final task to implement Solace as "subscribing the topic" where I will be using same virtual function as call back method of existing base class.
In order to do that, I divided the task into stepd and in first step I created simple class and trying to use member function as callback methond, but I am getting the error. Please suggest what should be approach I should follow.
In below code, sessionMessageReceiveCallback
is callback method, whenever messaged is published to TestTopic, sessionMessageReceiveCallback
is called.
I need to call virtual method in below line of code:
sessionFuncInfo.rxMsgInfo.callback_p = sessionMessageReceiveCallback;
sessionFuncInfo.rxMsgInfo.user_p = NULL;
Below is the full code:
os.h
#pragma once
/** @example Intro/os.h
*/
/*
* OS-specific methods for abstracting.
* Copyright 2008-2019 Solace Corporation. All rights reserved.
*/
#ifndef ___OS_H_
#define ___OS_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef WIN32
#define _WIN32_WINNT 0x400 /* Require Windows NT5 (2000, XP, 2003) for SignalObjectAndWait */
#include <winsock2.h>
#include <windows.h>
#include <winbase.h>
#define SLEEP(sec) Sleep ( (sec) * 1000 )
#define strcasecmp (_stricmp)
#define strncasecmp (_strnicmp)
#else
#include <unistd.h>
#define SLEEP(sec) sleep ( (sec) )
#endif
#ifdef __cplusplus
}
#endif
#endif
TopicSubscr.h
#include "os.h"
#include "solclient/solClient.h"
#include "solclient/solClientMsg.h"
class TopicSubscr
{
private :
solClient_rxMsgCallback_returnCode_t
sessionMessageReceiveCallback(solClient_opaqueSession_pt opaqueSession_p,
solClient_opaqueMsg_pt msg_p, void* user_p);
public :
solClient_opaqueSession_pt session_p;
static int msgCount;
explicit TopicSubscr();
~TopicSubscr();
};
TopicSubscr.cpp
#include "TopicSubscr.h"
/* Message Count */
static int msgCount = 0;
/*****************************************************************************
* sessionMessageReceiveCallback
*
* The message callback is invoked for each Direct message received by
* the Session. In this sample, the message is printed to the screen.
*****************************************************************************/
solClient_rxMsgCallback_returnCode_t
TopicSubscr::sessionMessageReceiveCallback(solClient_opaqueSession_pt opaqueSession_p, solClient_opaqueMsg_pt msg_p, void* user_p)
{
printf("Received message:\n");
solClient_msg_dump(msg_p, NULL, 0);
printf("\n");
//msgCount++;
return SOLCLIENT_CALLBACK_OK;
}
/*****************************************************************************
* sessionEventCallback
*
* The event callback function is mandatory for session creation.
*****************************************************************************/
void
sessionEventCallback(solClient_opaqueSession_pt opaqueSession_p,
solClient_session_eventCallbackInfo_pt eventInfo_p, void* user_p)
{
}
TopicSubscr::TopicSubscr()
{
/* Context */
solClient_opaqueContext_pt context_p;
solClient_context_createFuncInfo_t contextFuncInfo = SOLCLIENT_CONTEXT_CREATEFUNC_INITIALIZER;
/* Session */
solClient_session_createFuncInfo_t sessionFuncInfo = SOLCLIENT_SESSION_CREATEFUNC_INITIALIZER;
/* Session Properties */
const char* sessionProps[25] = { 0, };
int propIndex = 0;
/*************************************************************************
* Initialize the API (and setup logging level)
*************************************************************************/
/* solClient needs to be initialized before any other API calls. */
solClient_initialize(SOLCLIENT_LOG_DEFAULT_FILTER, NULL);
printf("TopicSubscriber initializing...\n");
/*************************************************************************
* Create a Context
*************************************************************************/
/*
* Create a Context, and specify that the Context thread be created
* automatically instead of having the application create its own
* Context thread.
*/
solClient_context_create(SOLCLIENT_CONTEXT_PROPS_DEFAULT_WITH_CREATE_THREAD,
&context_p, &contextFuncInfo, sizeof(contextFuncInfo));
/*************************************************************************
* Create and connect a Session
*************************************************************************/
/* Configure the Session function information. */
sessionFuncInfo.rxMsgInfo.callback_p = sessionMessageReceiveCallback;
sessionFuncInfo.rxMsgInfo.user_p = NULL;
sessionFuncInfo.eventInfo.callback_p = sessionEventCallback; // <-- Error here
sessionFuncInfo.eventInfo.user_p = NULL;
/* Configure the Session properties. */
propIndex = 0;
sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_HOST;
sessionProps[propIndex++] = "127.0.0.1:55555";
sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_VPN_NAME;
sessionProps[propIndex++] = "default";
sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_USERNAME;
sessionProps[propIndex++] = "admin";
sessionProps[propIndex++] = SOLCLIENT_SESSION_PROP_PASSWORD;
sessionProps[propIndex++] = "admin";
/* Create the Session. */
solClient_session_create(sessionProps,
context_p,
&session_p, &sessionFuncInfo, sizeof(sessionFuncInfo));
/* Connect the Session. */
solClient_session_connect(session_p);
/*************************************************************************
* Subscribe
*************************************************************************/
solClient_session_topicSubscribeExt(session_p,
SOLCLIENT_SUBSCRIBE_FLAGS_WAITFORCONFIRM, "TestTopic");
/*************************************************************************
* Wait for message
*************************************************************************/
printf("Waiting for message......\n");
fflush(stdout);
while (true) {
SLEEP(1);
}
printf("Exiting.\n");
}
TopicSubscr::~TopicSubscr()
{
/*************************************************************************
* Unsubscribe
*************************************************************************/
solClient_session_topicUnsubscribeExt(session_p,
SOLCLIENT_SUBSCRIBE_FLAGS_WAITFORCONFIRM,
"TestTopic");
/*************************************************************************
* Cleanup
*************************************************************************/
/* Cleanup solClient. */
solClient_cleanup();
}
Main.cpp
#include "TopicSubscr.h"
int main()
{
TopicSubscr subsc;
return 0;
}
Compilation error I am getting :
> C:\SolaceCCode\solace-samples-c-master\build\intro\win\VS2008\TopicSubscriber\TopicSubscr.cpp(76,73): error C3867: 'TopicSubscr::sessionMessageReceiveCallback': non-standard syntax; use '&' to create a pointer to member
2> C:\SolaceCCode\solace-samples-c-master\build\intro\win\VS2008\TopicSubscriber\TopicSubscr.cpp(76,73): error C2440: '=': cannot convert from 'solClient_rxMsgCallback_returnCode_t (__thiscall TopicSubscr::* )(solClient_opaqueSession_pt,solClient_opaqueMsg_pt,void *)' to 'solClient_session_rxMsgCallbackFunc_t'
2> C:\SolaceCCode\solace-samples-c-master\build\intro\win\VS2008\TopicSubscriber\TopicSubscr.cpp(76,44): message : There is no context in which this conversion is possible
Reference to solclient.h :
Reference to solClientMsg.h :
Example I used for reference :
Upvotes: 0
Views: 204
Reputation: 84
The main problem here is that you can't use a pointer to member function where a function pointer is expected. The error is about sessionMessageReceiveCallback
.
What you can do here for example:
user_p
to this
when setting callbacks. Note that it will be given back to you as one of the callback arguments.user_p
pointer inside the static callback.class TopicSubscr
{
private :
static solClient_rxMsgCallback_returnCode_t
sessionMessageReceiveCallback(solClient_opaqueSession_pt opaqueSession_p, solClient_opaqueMsg_pt msg_p, void* user_p)
{
static_cast<TopicSubscr*>(user_p)->myCallback(msg_p);
}
void myCallback(solClient_opaqueMsg_pt msg_p)
{
//now you are back inside your object
}
...
And when you set up the callbacks, you can use the name of the static function.
sessionFuncInfo.rxMsgInfo.callback_p = sessionMessageReceiveCallback;
sessionFuncInfo.rxMsgInfo.user_p = this; // <-- Here you set the object on which you'll call the callback method from the static function
Upvotes: 0