AllJoyn+C++开发案例-windows跨设备调用方法
2016-04-18 22:39
441 查看
AllJoyn+C++开发案例-windows跨设备调用方法
按照上一篇的AllJoyn+Android开发案例-android跨设备调用方法中,步骤二-开始着手windows间的跨平台方法例程的编写。具体参考上一篇:http://blog.csdn.net/jsjdtb356/article/details/51179564。
不同于java,windows编程的api core官网并没有给出介绍,如下图,地址:https://allseenalliance.org/framework/documentation/develop/api-guide/core。
![](http://img.blog.csdn.net/20160418212102630?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
无奈再去找building下关于windows的介绍,地址: https://allseenalliance.org/framework/documentation/develop/building/windows/build-source,主要说的都是一些工具
VS,python,junit,scons等等,最后才有一些关于运行测试实例的话,基本没有什么帮助。然后去下载地址下载了
Windows SDK(64bit)VS2012版本的包。解压后的文件目录如下:
![](http://img.blog.csdn.net/20160418213108869?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
注意我红色框出来的部分,解压后会有两个版本出来,一个是release版,一个debug版,在后面VS调试时,会有区分的。然后我再cpp包下bin中的samples实例中,去找了实例chat来运行,可以实现不同window设备之间的相互聊天。然后问题来了,就是如何自己实现一个alljoyn的实例。我参考的是cpp下的sample下的basic中的源码实例,basic源码实例中也是包含了,一个server和一个client,然后client去调用server的方法。
下面我先直接贴上server和client的源码,大家先看server和client的main方法,对过程有个大致认识。我的理解是实现过程和android端过程基本相同,在总线接口的实现方面不同,C++用了InterfaceDescription这样一个接口描述类来帮助接口的实现。
server源码:
step1:VS2015新建控制台工程之后,选择调试/属性,出现如下图:
![](http://img.blog.csdn.net/20160418214952484?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
注意:我的包名称是-Windows SDK(64bit)VS2012。
配置选择release,因为我用的是sdk下的release包,请对应选择。平台64位,我下载的包是64位,请对应选择。平台工具集是VS2012,不是默认的2015,因为我的包是2012。平台工具集没有VS2012的话,去下载VS2012安装完成就有了,或者直接使用VS2012。
添加附加包含目录:
![](http://img.blog.csdn.net/20160418215757198?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
红色框框出来的部分,添加release包下的cpp下的inc文件夹,包含头文件。
附加库目录:
![](http://img.blog.csdn.net/20160418220252007?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
框出来部分,添加release下的cpp下的lib目录。
添加附加依赖项:
![](http://img.blog.csdn.net/20160418220458258?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
框出来的部分,添加ajrouter.lib和alljoyn.lib静态库。
到这里编写代码前的环境基本完成了。
step2:
测试代码编写,一个简单的client和server的测试代码如上所示,C++总线接口的实现:
interface在server中的实现代码:
下面我们再看看client如何实现的方法调用:
总结:可能会出现下面的情况,step1和step2做完成之后会出现大量的Link错误,尽量去尝试着修改。没有办法的办法是,导入源码工程去实现想要的功能,这样可移植比较低。方法调用的流程几乎和android端的是一致的,在总线interface的声明和实现上有差别。另外client和server要统一的4个地方,和android端也是一致的,如下:
按照上一篇的AllJoyn+Android开发案例-android跨设备调用方法中,步骤二-开始着手windows间的跨平台方法例程的编写。具体参考上一篇:http://blog.csdn.net/jsjdtb356/article/details/51179564。
不同于java,windows编程的api core官网并没有给出介绍,如下图,地址:https://allseenalliance.org/framework/documentation/develop/api-guide/core。
无奈再去找building下关于windows的介绍,地址: https://allseenalliance.org/framework/documentation/develop/building/windows/build-source,主要说的都是一些工具
VS,python,junit,scons等等,最后才有一些关于运行测试实例的话,基本没有什么帮助。然后去下载地址下载了
Windows SDK(64bit)VS2012版本的包。解压后的文件目录如下:
注意我红色框出来的部分,解压后会有两个版本出来,一个是release版,一个debug版,在后面VS调试时,会有区分的。然后我再cpp包下bin中的samples实例中,去找了实例chat来运行,可以实现不同window设备之间的相互聊天。然后问题来了,就是如何自己实现一个alljoyn的实例。我参考的是cpp下的sample下的basic中的源码实例,basic源码实例中也是包含了,一个server和一个client,然后client去调用server的方法。
下面我先直接贴上server和client的源码,大家先看server和client的main方法,对过程有个大致认识。我的理解是实现过程和android端过程基本相同,在总线接口的实现方面不同,C++用了InterfaceDescription这样一个接口描述类来帮助接口的实现。
server源码:
#include <qcc/platform.h> #include <assert.h> #include <signal.h> #include <stdio.h> #include <vector> #include <qcc/String.h> #include <alljoyn/AllJoynStd.h> #include <alljoyn/BusAttachment.h> #include <alljoyn/BusObject.h> #include <alljoyn/DBusStd.h> #include <alljoyn/Init.h> #include <alljoyn/MsgArg.h> #include <alljoyn/version.h> #include <alljoyn/Status.h> using namespace std; using namespace qcc; using namespace ajn; /*constants*/ static const char* INTERFACE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_PATH = "/sample"; static const SessionPort SERVICE_PORT = 25; static volatile sig_atomic_t s_interrupt = false; static void CDECL_CALL SigIntHandler(int sig) { QCC_UNUSED(sig); s_interrupt = true; } class BasicSampleObject : public BusObject { public: BasicSampleObject(BusAttachment& bus, const char* path) : BusObject(path) { /** Add the test interface to this object */ const InterfaceDescription* exampleIntf = bus.GetInterface(INTERFACE_NAME); assert(exampleIntf); AddInterface(*exampleIntf); /** Register the method handlers with the object */ const MethodEntry methodEntries[] = { { exampleIntf->GetMember("cat"), static_cast<MessageReceiver::MethodHandler>(&BasicSampleObject::Cat) } }; QStatus status = AddMethodHandlers(methodEntries, sizeof(methodEntries) / sizeof(methodEntries[0])); if (ER_OK != status) { printf("Failed to register method handlers for BasicSampleObject.\n"); } } void ObjectRegistered() { BusObject::ObjectRegistered(); printf("ObjectRegistered has been called.\n"); } void Cat(const InterfaceDescription::Member* member, Message& msg) { QCC_UNUSED(member); /* Concatenate the two input strings and reply with the result. */ qcc::String inStr1 = msg->GetArg(0)->v_string.str; qcc::String inStr2 = msg->GetArg(1)->v_string.str; qcc::String outStr = inStr1 + inStr2; MsgArg outArg("s", outStr.c_str()); QStatus status = MethodReply(msg, &outArg, 1); if (ER_OK != status) { printf("Ping: Error sending reply.\n"); } } }; class MyBusListener : public BusListener, public SessionPortListener { void NameOwnerChanged(const char* busName, const char* previousOwner, const char* newOwner) { if (newOwner && (0 == strcmp(busName, SERVICE_NAME))) { printf("NameOwnerChanged: name=%s, oldOwner=%s, newOwner=%s.\n", busName, previousOwner ? previousOwner : "<none>", newOwner ? newOwner : "<none>"); } } bool AcceptSessionJoiner(SessionPort sessionPort, const char* joiner, const SessionOpts& opts) { if (sessionPort != SERVICE_PORT) { printf("Rejecting join attempt on unexpected session port %d.\n", sessionPort); return false; } printf("Accepting join session request from %s (opts.proximity=%x, opts.traffic=%x, opts.transports=%x).\n", joiner, opts.proximity, opts.traffic, opts.transports); return true; } }; /** The bus listener object. */ static MyBusListener s_busListener; /** Top level message bus object. */ static BusAttachment* s_msgBus = NULL; /** Create the interface, report the result to stdout, and return the result status. */ QStatus CreateInterface(void) { /* Add org.alljoyn.Bus.method_sample interface */ InterfaceDescription* testIntf = NULL; QStatus status = s_msgBus->CreateInterface(INTERFACE_NAME, testIntf); if (status == ER_OK) { printf("Interface created.\n"); testIntf->AddMethod("cat", "ss", "s", "inStr1,inStr2,outStr", 0); testIntf->Activate(); } else { printf("Failed to create interface '%s'.\n", INTERFACE_NAME); } return status; } /** Register the bus object and connect, report the result to stdout, and return the status code. */ QStatus RegisterBusObject(BasicSampleObject* obj) { QStatus status = s_msgBus->RegisterBusObject(*obj); if (ER_OK == status) { printf("RegisterBusObject succeeded.\n"); } else { printf("RegisterBusObject failed (%s).\n", QCC_StatusText(status)); } return status; } /** Connect, report the result to stdout, and return the status code. */ QStatus ConnectBusAttachment(void) { QStatus status = s_msgBus->Connect(); if (ER_OK == status) { printf("Connect to '%s' succeeded.\n", s_msgBus->GetConnectSpec().c_str()); } else { printf("Failed to connect to '%s' (%s).\n", s_msgBus->GetConnectSpec().c_str(), QCC_StatusText(status)); } return status; } /** Start the message bus, report the result to stdout, and return the status code. */ QStatus StartMessageBus(void) { QStatus status = s_msgBus->Start(); if (ER_OK == status) { printf("BusAttachment started.\n"); } else { printf("Start of BusAttachment failed (%s).\n", QCC_StatusText(status)); } return status; } /** Create the session, report the result to stdout, and return the status code. */ QStatus CreateSession(TransportMask mask) { SessionOpts opts(SessionOpts::TRAFFIC_MESSAGES, false, SessionOpts::PROXIMITY_ANY, mask); SessionPort sp = SERVICE_PORT; QStatus status = s_msgBus->BindSessionPort(sp, opts, s_busListener); if (ER_OK == status) { printf("BindSessionPort succeeded.\n"); } else { printf("BindSessionPort failed (%s).\n", QCC_StatusText(status)); } return status; } /** Advertise the service name, report the result to stdout, and return the status code. */ QStatus AdvertiseName(TransportMask mask) { QStatus status = s_msgBus->AdvertiseName(SERVICE_NAME, mask); if (ER_OK == status) { printf("Advertisement of the service name '%s' succeeded.\n", SERVICE_NAME); } else { printf("Failed to advertise name '%s' (%s).\n", SERVICE_NAME, QCC_StatusText(status)); } return status; } /** Request the service name, report the result to stdout, and return the status code. */ QStatus RequestName(void) { const uint32_t flags = DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE; QStatus status = s_msgBus->RequestName(SERVICE_NAME, flags); if (ER_OK == status) { printf("RequestName('%s') succeeded.\n", SERVICE_NAME); } else { printf("RequestName('%s') failed (status=%s).\n", SERVICE_NAME, QCC_StatusText(status)); } return status; } /** Wait for SIGINT before continuing. */ void WaitForSigInt(void) { while (s_interrupt == false) { #ifdef _WIN32 Sleep(100); #else usleep(100 * 1000); #endif } } /** Main entry point */ int CDECL_CALL main(int argc, char** argv, char** envArg) { QCC_UNUSED(argc); QCC_UNUSED(argv); QCC_UNUSED(envArg); if (AllJoynInit() != ER_OK) { return 1; } #ifdef ROUTER if (AllJoynRouterInit() != ER_OK) { AllJoynShutdown(); return 1; } #endif printf("AllJoyn Library version: %s.\n", ajn::GetVersion()); printf("AllJoyn Library build info: %s.\n", ajn::GetBuildInfo()); /* Install SIGINT handler */ signal(SIGINT, SigIntHandler); QStatus status = ER_OK; BasicSampleObject* testObj = NULL; /* Create message bus */ s_msgBus = new BusAttachment("myApp", true); if (s_msgBus) { if (ER_OK == status) { status = CreateInterface(); } if (ER_OK == status) { s_msgBus->RegisterBusListener(s_busListener); } if (ER_OK == status) { status = StartMessageBus(); } testObj = new BasicSampleObject(*s_msgBus, SERVICE_PATH); if (ER_OK == status) { status = RegisterBusObject(testObj); } if (ER_OK == status) { status = ConnectBusAttachment(); } /* * Advertise this service on the bus. * There are three steps to advertising this service on the bus. * 1) Request a well-known name that will be used by the client to discover * this service. * 2) Create a session. * 3) Advertise the well-known name. */ if (ER_OK == status) { status = RequestName(); } const TransportMask SERVICE_TRANSPORT_TYPE = TRANSPORT_ANY; if (ER_OK == status) { status = CreateSession(SERVICE_TRANSPORT_TYPE); } if (ER_OK == status) { status = AdvertiseName(SERVICE_TRANSPORT_TYPE); } /* Perform the service asynchronously until the user signals for an exit. */ if (ER_OK == status) { WaitForSigInt(); } } else { status = ER_OUT_OF_MEMORY; } /* Clean up */ delete s_msgBus; s_msgBus = NULL; delete testObj; testObj = NULL; printf("Basic service exiting with status 0x%04x (%s).\n", status, QCC_StatusText(status)); #ifdef ROUTER AllJoynRouterShutdown(); #endif AllJoynShutdown(); return (int) status; }client源码:
#include <qcc/platform.h> #include <assert.h> #include <signal.h> #include <stdio.h> #include <vector> #include <qcc/String.h> #include <alljoyn/AllJoynStd.h> #include <alljoyn/BusAttachment.h> #include <alljoyn/Init.h> #include <alljoyn/Status.h> #include <alljoyn/version.h> using namespace std; using namespace qcc; using namespace ajn; /** Static top level message bus object */ static BusAttachment* g_msgBus = NULL; /*constants*/ static const char* INTERFACE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_PATH = "/sample"; static const SessionPort SERVICE_PORT = 25; static bool s_joinComplete = false; static String s_sessionHost; static SessionId s_sessionId = 0; static volatile sig_atomic_t s_interrupt = false; static void CDECL_CALL SigIntHandler(int sig) { QCC_UNUSED(sig); s_interrupt = true; } /** AllJoynListener receives discovery events from AllJoyn */ class MyBusListener : public BusListener, public SessionListener { public: void FoundAdvertisedName(const char* name, TransportMask transport, const char* namePrefix) { if (0 == strcmp(name, SERVICE_NAME) && s_sessionHost.empty()) { printf("FoundAdvertisedName(name='%s', transport = 0x%x, prefix='%s')\n", name, transport, namePrefix); /* We found a remote bus that is advertising basic service's well-known name so connect to it. */ /* Since we are in a callback we must enable concurrent callbacks before calling a synchronous method. */ s_sessionHost = name; g_msgBus->EnableConcurrentCallbacks(); SessionOpts opts(SessionOpts::TRAFFIC_MESSAGES, false, SessionOpts::PROXIMITY_ANY, TRANSPORT_ANY); QStatus status = g_msgBus->JoinSession(name, SERVICE_PORT, this, s_sessionId, opts); if (ER_OK == status) { printf("JoinSession SUCCESS (Session id=%d).\n", s_sessionId); } else { printf("JoinSession failed (status=%s).\n", QCC_StatusText(status)); } s_joinComplete = true; } } void NameOwnerChanged(const char* busName, const char* previousOwner, const char* newOwner) { if (newOwner && (0 == strcmp(busName, SERVICE_NAME))) { printf("NameOwnerChanged: name='%s', oldOwner='%s', newOwner='%s'.\n", busName, previousOwner ? previousOwner : "<none>", newOwner ? newOwner : "<none>"); } } }; /** Create the interface, report the result to stdout, and return the result status. */ QStatus CreateInterface(void) { /* Add org.alljoyn.Bus.method_sample interface */ InterfaceDescription* testIntf = NULL; QStatus status = g_msgBus->CreateInterface(INTERFACE_NAME, testIntf); if (status == ER_OK) { printf("Interface '%s' created.\n", INTERFACE_NAME); testIntf->AddMethod("cat", "ss", "s", "inStr1,inStr2,outStr", 0); testIntf->Activate(); } else { printf("Failed to create interface '%s'.\n", INTERFACE_NAME); } return status; } /** Start the message bus, report the result to stdout, and return the result status. */ QStatus StartMessageBus(void) { QStatus status = g_msgBus->Start(); if (ER_OK == status) { printf("BusAttachment started.\n"); } else { printf("BusAttachment::Start failed.\n"); } return status; } /** Handle the connection to the bus, report the result to stdout, and return the result status. */ QStatus ConnectToBus(void) { QStatus status = g_msgBus->Connect(); if (ER_OK == status) { printf("BusAttachment connected to '%s'.\n", g_msgBus->GetConnectSpec().c_str()); } else { printf("BusAttachment::Connect('%s') failed.\n", g_msgBus->GetConnectSpec().c_str()); } return status; } /** Register a bus listener in order to get discovery indications and report the event to stdout. */ void RegisterBusListener(void) { /* Static bus listener */ static MyBusListener s_busListener; g_msgBus->RegisterBusListener(s_busListener); printf("BusListener Registered.\n"); } /** Begin discovery on the well-known name of the service to be called, report the result to stdout, and return the result status. */ QStatus FindAdvertisedName(void) { /* Begin discovery on the well-known name of the service to be called */ QStatus status = g_msgBus->FindAdvertisedName(SERVICE_NAME); if (status == ER_OK) { printf("org.alljoyn.Bus.FindAdvertisedName ('%s') succeeded.\n", SERVICE_NAME); } else { printf("org.alljoyn.Bus.FindAdvertisedName ('%s') failed (%s).\n", SERVICE_NAME, QCC_StatusText(status)); } return status; } /** Wait for join session to complete, report the event to stdout, and return the result status. */ QStatus WaitForJoinSessionCompletion(void) { unsigned int count = 0; while (!s_joinComplete && !s_interrupt) { if (0 == (count++ % 10)) { printf("Waited %u seconds for JoinSession completion.\n", count / 10); } #ifdef _WIN32 Sleep(100); #else usleep(100 * 1000); #endif } return s_joinComplete && !s_interrupt ? ER_OK : ER_ALLJOYN_JOINSESSION_REPLY_CONNECT_FAILED; } /** Do a method call, report the result to stdout, and return the result status. */ QStatus MakeMethodCall(void) { ProxyBusObject remoteObj(*g_msgBus, SERVICE_NAME, SERVICE_PATH, s_sessionId); const InterfaceDescription* alljoynTestIntf = g_msgBus->GetInterface(INTERFACE_NAME); assert(alljoynTestIntf); remoteObj.AddInterface(*alljoynTestIntf); Message reply(*g_msgBus); MsgArg inputs[2]; inputs[0].Set("s", "Hello "); inputs[1].Set("s", "World!"); QStatus status = remoteObj.MethodCall(INTERFACE_NAME, "cat", inputs, 2, reply, 5000); if (ER_OK == status) { printf("'%s.%s' (path='%s') returned '%s'.\n", SERVICE_NAME, "cat", SERVICE_PATH, reply->GetArg(0)->v_string.str); } else { printf("MethodCall on '%s.%s' failed.", SERVICE_NAME, "cat"); } return status; } /** Main entry point */ int CDECL_CALL main(int argc, char** argv, char** envArg) { QCC_UNUSED(argc); QCC_UNUSED(argv); QCC_UNUSED(envArg); if (AllJoynInit() != ER_OK) { return 1; } #ifdef ROUTER if (AllJoynRouterInit() != ER_OK) { AllJoynShutdown(); return 1; } #endif printf("AllJoyn Library version: %s.\n", ajn::GetVersion()); printf("AllJoyn Library build info: %s.\n", ajn::GetBuildInfo()); /* Install SIGINT handler. */ signal(SIGINT, SigIntHandler); QStatus status = ER_OK; /* Create message bus. */ g_msgBus = new BusAttachment("myApp", true); /* This test for NULL is only required if new() behavior is to return NULL * instead of throwing an exception upon an out of memory failure. */ if (!g_msgBus) { status = ER_OUT_OF_MEMORY; } if (ER_OK == status) { status = CreateInterface(); } if (ER_OK == status) { status = StartMessageBus(); } if (ER_OK == status) { status = ConnectToBus(); } if (ER_OK == status) { RegisterBusListener(); status = FindAdvertisedName(); } if (ER_OK == status) { status = WaitForJoinSessionCompletion(); } if (ER_OK == status) { status = MakeMethodCall(); } /* Deallocate bus */ delete g_msgBus; g_msgBus = NULL; printf("Basic client exiting with status 0x%04x (%s).\n", status, QCC_StatusText(status)); #ifdef ROUTER AllJoynRouterShutdown(); #endif AllJoynShutdown(); return (int) status; }下面总结一下一般步骤:
step1:VS2015新建控制台工程之后,选择调试/属性,出现如下图:
注意:我的包名称是-Windows SDK(64bit)VS2012。
配置选择release,因为我用的是sdk下的release包,请对应选择。平台64位,我下载的包是64位,请对应选择。平台工具集是VS2012,不是默认的2015,因为我的包是2012。平台工具集没有VS2012的话,去下载VS2012安装完成就有了,或者直接使用VS2012。
添加附加包含目录:
红色框框出来的部分,添加release包下的cpp下的inc文件夹,包含头文件。
附加库目录:
框出来部分,添加release下的cpp下的lib目录。
添加附加依赖项:
框出来的部分,添加ajrouter.lib和alljoyn.lib静态库。
到这里编写代码前的环境基本完成了。
step2:
测试代码编写,一个简单的client和server的测试代码如上所示,C++总线接口的实现:
/** Create the interface, report the result to stdout, and return the result status. */ QStatus CreateInterface(void) { /* Add org.alljoyn.Bus.method_sample interface */ InterfaceDescription* testIntf = NULL; QStatus status = s_msgBus->CreateInterface(INTERFACE_NAME, testIntf); if (status == ER_OK) { printf("Interface created.\n"); testIntf->AddMethod("cat", "ss", "s", "inStr1,inStr2,outStr", 0); testIntf->Activate(); } else { printf("Failed to create interface '%s'.\n", INTERFACE_NAME); } return status; }interface的声明,INTERFACE_NAME是全局变量,InterfaceDescription实现接口的描述,增加方法cat方法,传入两个str,传出一个str。
interface在server中的实现代码:
class BasicSampleObject : public BusObject { public: BasicSampleObject(BusAttachment& bus, const char* path) : BusObject(path) { /** Add the test interface to this object */ const InterfaceDescription* exampleIntf = bus.GetInterface(INTERFACE_NAME); assert(exampleIntf); AddInterface(*exampleIntf); /** Register the method handlers with the object */ const MethodEntry methodEntries[] = { { exampleIntf->GetMember("cat"), static_cast<MessageReceiver::MethodHandler>(&BasicSampleObject::Cat) } }; QStatus status = AddMethodHandlers(methodEntries, sizeof(methodEntries) / sizeof(methodEntries[0])); if (ER_OK != status) { printf("Failed to register method handlers for BasicSampleObject.\n"); } } void ObjectRegistered() { BusObject::ObjectRegistered(); printf("ObjectRegistered has been called.\n"); } void Cat(const InterfaceDescription::Member* member, Message& msg) { QCC_UNUSED(member); /* Concatenate the two input strings and reply with the result. */ qcc::String inStr1 = msg->GetArg(0)->v_string.str; qcc::String inStr2 = msg->GetArg(1)->v_string.str; qcc::String outStr = inStr1 + inStr2; MsgArg outArg("s", outStr.c_str()); QStatus status = MethodReply(msg, &outArg, 1); if (ER_OK != status) { printf("Ping: Error sending reply.\n"); } } };BasicSampleObject类的构造函数中,指定了接口中的cat方法入口为,BasicSampleObject类中的Cat方法,我们在Cat方法中去实现server具体的操作,测试的例子是两个字符串的加法。注意这里和Java中不同的是,函数的参数是放在Message类的对象中的,返回值的方法调用的是MethodReplay。
下面我们再看看client如何实现的方法调用:
/** Do a method call, report the result to stdout, and return the result status. */ QStatus MakeMethodCall(void) { ProxyBusObject remoteObj(*g_msgBus, SERVICE_NAME, SERVICE_PATH, s_sessionId); const InterfaceDescription* alljoynTestIntf = g_msgBus->GetInterface(INTERFACE_NAME); assert(alljoynTestIntf); remoteObj.AddInterface(*alljoynTestIntf); Message reply(*g_msgBus); MsgArg inputs[2]; inputs[0].Set("s", "Hello "); inputs[1].Set("s", "World!"); QStatus status = remoteObj.MethodCall(INTERFACE_NAME, "cat", inputs, 2, reply, 5000); if (ER_OK == status) { printf("'%s.%s' (path='%s') returned '%s'.\n", SERVICE_NAME, "cat", SERVICE_PATH, reply->GetArg(0)->v_string.str); } else { printf("MethodCall on '%s.%s' failed.", SERVICE_NAME, "cat"); } return status; }同java中相同的是创建代理对象,不同的是java中直接从代理对象获得接口之后,使用(void or String)interface.method()就实现了方法的调用和返回。这里用了接口描述,没法直接向java一样的调用方法,传入参数以MsgArg数组实现,传出参数以Message实现。
总结:可能会出现下面的情况,step1和step2做完成之后会出现大量的Link错误,尽量去尝试着修改。没有办法的办法是,导入源码工程去实现想要的功能,这样可移植比较低。方法调用的流程几乎和android端的是一致的,在总线interface的声明和实现上有差别。另外client和server要统一的4个地方,和android端也是一致的,如下:
static const char* INTERFACE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_NAME = "org.alljoyn.Bus.sample"; static const char* SERVICE_PATH = "/sample"; static const SessionPort SERVICE_PORT = 25;
相关文章推荐
- C++多线程调用Python多进程
- 插入排序(C++实现)
- C,C++,C#note
- c++宏定义
- C语言--memcpy和memmove
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++多态的实现原理
- c++避免内存泄漏
- C++问题小结--3.构造函数与析构函数关于其自身特点的简单代码陈述
- c++继承属性不具有多态性
- 计算某个日期起N天后的日期(C语言递归实现)
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- C语言中的全局变量定义与使用
- Ubuntu下编写C语言程序
- PAT (Basic Level) Practise (中文)1028. 人口普查(20)
- protobuf的编译与安装(教程)附带资源(亲测,Mac下可以用)
- 稀疏矩阵-压缩存储-列转置法- 一次定位快速转置法
- 单链表的头插、中插、尾插、删除、逆序、显示(C语言实现)
- 康托展开
- string类的实现(mystring)