Adding callback for C++ (still has bug for return values); adding struct as method...
authorrtrimana <rtrimana@uci.edu>
Sat, 5 Nov 2016 00:05:52 +0000 (17:05 -0700)
committerrtrimana <rtrimana@uci.edu>
Sat, 5 Nov 2016 00:05:52 +0000 (17:05 -0700)
28 files changed:
iotjava/iotrmi/C++/IoTRMICall.hpp
iotjava/iotrmi/C++/IoTRMIObject.hpp
iotjava/iotrmi/C++/IoTSocket.hpp
iotjava/iotrmi/C++/sample/CallBack.hpp
iotjava/iotrmi/C++/sample/CallBackInterface.hpp
iotjava/iotrmi/C++/sample/CallBack_CBSkeleton.hpp
iotjava/iotrmi/C++/sample/CallBack_CBStub.hpp
iotjava/iotrmi/C++/sample/CallBack_Skeleton.hpp
iotjava/iotrmi/C++/sample/CallBack_Stub.hpp
iotjava/iotrmi/C++/sample/StructC.cpp [new file with mode: 0644]
iotjava/iotrmi/C++/sample/StructC.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/sample/Test.cpp [new file with mode: 0644]
iotjava/iotrmi/C++/sample/Test2.cpp [new file with mode: 0644]
iotjava/iotrmi/C++/sample/TestClass.cpp
iotjava/iotrmi/C++/sample/TestClass.hpp
iotjava/iotrmi/C++/sample/TestClassInterface.hpp
iotjava/iotrmi/C++/sample/TestClass_Skeleton.cpp
iotjava/iotrmi/C++/sample/TestClass_Skeleton.hpp
iotjava/iotrmi/C++/sample/TestClass_Stub.cpp
iotjava/iotrmi/C++/sample/TestClass_Stub.hpp
iotjava/iotrmi/Java/sample/StructJ.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/StructMain.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/TestClass.java
iotjava/iotrmi/Java/sample/TestClassInterface.java
iotjava/iotrmi/Java/sample/TestClass_CBSkeleton.java
iotjava/iotrmi/Java/sample/TestClass_CBStub.java
iotjava/iotrmi/Java/sample/TestClass_Skeleton.java
iotjava/iotrmi/Java/sample/TestClass_Stub.java

index f498758..c749b02 100644 (file)
 
 #include <iostream>
 #include <string>
+#include <mutex>
 #include "IoTRMIUtil.hpp"
 #include "IoTSocketClient.hpp"
 
 using namespace std;
 
+mutex mtx;
+
 class IoTRMICall {
        public:
                IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult, 
@@ -80,14 +83,20 @@ IoTRMICall::~IoTRMICall() {
 void* IoTRMICall::remoteCall(int objectId, string methodSign, string retType, string paramCls[], 
                                                                void* paramObj[], int numParam, void* retObj) {
 
+       // Critical section that is used by different objects
+       lock_guard<mutex> guard(mtx);
        // Send input parameters
        int len = methodLength(paramCls, paramObj, numParam);
        char method[len];
+       cout << "Got in remoteCall!" << endl;
        methodToBytes(objectId, methodSign, paramCls, paramObj, method, numParam);
+       cout << "Executed methodToBytes in remoteCall!" << endl;
+       IoTRMIUtil::printBytes(method, len, false);
        // Send bytes
        fflush(NULL);
        rmiClient->sendBytes(method, len);
        fflush(NULL);
+       cout << "Got in remoteCall! 2" << endl;
        // Receive return value and return it to caller
        if (retType.compare("void") == 0)
                // Just make it NULL if it's a void return
index 366c6ef..084fb7b 100644 (file)
@@ -106,7 +106,10 @@ void IoTRMIObject::sendReturnObj(void* retObj, string type) {
 char* IoTRMIObject::getMethodBytes() {
 
        // Get method in bytes and update method length
+       cout << "Got into getMethodBytes()" << endl;
+       //fflush(NULL);
        methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
+       cout << "Got into getMethodBytes() 2" << endl;
        fflush(NULL);
        return methodBytes;
 }
index 46685f7..54f0234 100644 (file)
@@ -159,7 +159,7 @@ char* IoTSocket::receiveBytes(char* pVals, int* len)
        if (!receiveAck())
                return NULL;
 #endif
-
+       cout << "Socket 6!" << endl;
        return pVals;
 }
 
index a4b9db4..7774d76 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CALLBACK_HPP__
+#define _CALLBACK_HPP__
+
 #include <iostream>
 #include "CallBackInterface.hpp"
 
@@ -36,4 +39,5 @@ void CallBack::setInt(int _i) {
        intA = _i;
 }
 
+#endif
 
index 9864d6f..7364f8d 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CALLBACKINTERFACE_HPP__
+#define _CALLBACKINTERFACE_HPP__
+
 #include <iostream>
 
 using namespace std;
@@ -8,3 +11,5 @@ class CallBackInterface {
                virtual void    setInt(int _i) = 0;
 };
 
+#endif
+
index b2f56a2..7ed5f04 100644 (file)
@@ -1,6 +1,10 @@
+#ifndef _CALLBACK_CBSKELETON_HPP__
+#define _CALLBACK_CBSKELETON_HPP__
+
 #include <iostream>
+#include "CallBackInterface.hpp"
 #include "../IoTRMIObject.hpp"
-#include "CallBack.hpp"
+
 
 using namespace std;
 
@@ -9,7 +13,7 @@ class CallBack_CBSkeleton : public CallBackInterface {
                CallBack_CBSkeleton(CallBackInterface* _cb, int _objectId);
                ~CallBack_CBSkeleton();
 
-               void                                    invokeMethod(IoTRMIObject* rmiObj);
+               void*                                   invokeMethod(IoTRMIObject* rmiObj, string *type);
                int                                             printInt();
                void                                    setInt(int _i);
 
@@ -43,35 +47,41 @@ CallBack_CBSkeleton::~CallBack_CBSkeleton() {
 }
 
 
-void CallBack_CBSkeleton::invokeMethod(IoTRMIObject* rmiObj) {
+void* CallBack_CBSkeleton::invokeMethod(IoTRMIObject* rmiObj, string *type) {
 
        // Loop continuously waiting for incoming bytes
-       while (true) {
-
-               rmiObj->getMethodBytes();
-               string methodSign = rmiObj->getSignature();
-               cout << "Method sign: " << methodSign << endl;
-               
-               if (methodSign.compare("intprintInt()") == 0) {
-                       string paramCls[] = { };
-                       int numParam = 0;
-                       void* paramObj[] = { };
-                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
-                       int retVal = printInt();
-                       void* retObj = &retVal;
-                       rmiObj->sendReturnObj(retObj, "int");
-               } else if (methodSign.compare("voidsetInt(int)") == 0) {
-                       string paramCls[] = { "int" };
-                       int numParam = 1;
-                       int param1 = 1;
-                       void* paramObj[] = { &param1 };
-                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
-                       setInt(param1);
-               } else {
-                       string error = "Signature not recognized: " + string(methodSign);
-                       throw error;
-               }
+       void* retObj = NULL;
+       cout << "Get inside invoke method!" << endl;
+
+       //rmiObj->getMethodBytes();
+       cout << "Get inside invoke 2!" << endl;
+       string methodSign = rmiObj->getSignature();
+       cout << "Get inside invoke 3!" << endl;
+       cout << "Method sign: " << methodSign << endl;
+       
+       if (methodSign.compare("intprintInt()") == 0) {
+               string paramCls[] = { };
+               int numParam = 0;
+               void* paramObj[] = { };
+               rmiObj->getMethodParams(paramCls, numParam, paramObj);
+               int retVal = printInt();
+               retObj = &retVal;
+               *type = "int";
+               rmiObj->sendReturnObj(retObj, "int");
+       } else if (methodSign.compare("voidsetInt(int)") == 0) {
+               string paramCls[] = { "int" };
+               int numParam = 1;
+               int param1 = 1;
+               void* paramObj[] = { &param1 };
+               rmiObj->getMethodParams(paramCls, numParam, paramObj);
+               setInt(param1);
+               *type = "void";
+       } else {
+               string error = "Signature not recognized: " + string(methodSign);
+               throw error;
        }
+
+       return retObj;
 }
 
 
@@ -86,4 +96,5 @@ void CallBack_CBSkeleton::setInt(int _i) {
        cb->setInt(_i);
 }
 
+#endif
 
index 07b5b3c..090b2c4 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CALLBACK_CBSTUB_HPP__
+#define _CALLBACK_CBSTUB_HPP__
+
 #include <iostream>
 #include "CallBackInterface.hpp"
 #include "../IoTRMICall.hpp"
@@ -55,6 +58,7 @@ CallBack_CBStub::~CallBack_CBStub() {
 
 int CallBack_CBStub::printInt() {
 
+       cout << "Got here in printInt()" << endl;
        int numParam = 0;
        string sign = "intprintInt()";
        string retType = "int";
@@ -63,6 +67,7 @@ int CallBack_CBStub::printInt() {
        int retVal = 0;
        void* retObj = &retVal;
        rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
+       cout << "Return value from printInt(): " << retVal << endl;
        return retVal;
 }
 
@@ -78,4 +83,5 @@ void CallBack_CBStub::setInt(int _i) {
        rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
 }
 
+#endif
 
index 36477ac..b087046 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CALLBACK_SKELETON_HPP__
+#define _CALLBACK_SKELETON_HPP__
+
 #include <iostream>
 #include "../IoTRMIObject.hpp"
 #include "CallBack.hpp"
@@ -91,4 +94,5 @@ void CallBack_Skeleton::setInt(int _i) {
        cb->setInt(_i);
 }
 
+#endif
 
index b1fa580..42f1059 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CALLBACK_STUB_HPP__
+#define _CALLBACK_STUB_HPP__
+
 #include <iostream>
 #include "CallBackInterface.hpp"
 #include "../IoTRMICall.hpp"
@@ -80,4 +83,4 @@ void CallBack_Stub::setInt(int _i) {
        rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
 }
 
-
+#endif
diff --git a/iotjava/iotrmi/C++/sample/StructC.cpp b/iotjava/iotrmi/C++/sample/StructC.cpp
new file mode 100644 (file)
index 0000000..060d255
--- /dev/null
@@ -0,0 +1,33 @@
+#include <iostream>
+#include <vector>
+#include "StructC.hpp"
+
+int main(int argc, char *argv[]) {
+
+       data testdata;
+       testdata.name = "Rahmadi";
+       testdata.value = 0.123;
+       testdata.year = 2016;
+
+       /*cout << "Name: " << testdata.name << endl;
+       cout << "Value: " << testdata.value << endl;
+       cout << "Year: " << testdata.year << endl;*/
+
+       vector<data> dataset;
+       data testdata2;
+       testdata2.name = "Trimananda";
+       testdata2.value = 0.223;
+       testdata2.year = 2017;
+       
+       dataset.push_back(testdata);
+       dataset.push_back(testdata2);
+
+       for (data dat : dataset) {
+
+               cout << "Name: " << dat.name << endl;
+               cout << "Value: " << dat.value << endl;
+               cout << "Year: " << dat.year << endl;
+       }
+
+       return 0;
+}
diff --git a/iotjava/iotrmi/C++/sample/StructC.hpp b/iotjava/iotrmi/C++/sample/StructC.hpp
new file mode 100644 (file)
index 0000000..b762f5e
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _STRUCTC_HPP__
+#define _STRUCTC_HPP__
+
+using namespace std;
+
+struct data {
+       string  name;
+       float   value;
+       int             year;
+};
+
+#endif
+
diff --git a/iotjava/iotrmi/C++/sample/Test.cpp b/iotjava/iotrmi/C++/sample/Test.cpp
new file mode 100644 (file)
index 0000000..8d1771e
--- /dev/null
@@ -0,0 +1,32 @@
+#include <iostream>
+#include <map>
+#include <string>
+#include <chrono>
+#include <thread>
+#include <mutex>
+std::map<std::string, std::string> g_pages;
+std::mutex g_pages_mutex;
+void save_page(const std::string &url)
+{
+    // simulate a long page fetch
+    std::this_thread::sleep_for(std::chrono::seconds(2));
+    std::string result = "fake content";
+    std::lock_guard<std::mutex> guard(g_pages_mutex);
+    g_pages[url] = result;
+}
+int main() 
+{
+    std::thread t1(save_page, "http://foo");
+    std::thread t2(save_page, "http://bar");
+    t1.join();
+    t2.join();
+    // safe to access g_pages without lock now, as the threads are joined
+    for (const auto &pair : g_pages) {
+        std::cout << pair.first << " => " << pair.second << '\n';
+    }
+}
\ No newline at end of file
diff --git a/iotjava/iotrmi/C++/sample/Test2.cpp b/iotjava/iotrmi/C++/sample/Test2.cpp
new file mode 100644 (file)
index 0000000..3996381
--- /dev/null
@@ -0,0 +1,25 @@
+// mutex example
+#include <iostream>       // std::cout
+#include <thread>         // std::thread
+#include <mutex>          // std::mutex
+
+std::mutex mtx;           // mutex for critical section
+
+void print_block (int n, char c) {
+  // critical section (exclusive access to std::cout signaled by locking mtx):
+  mtx.lock();
+  for (int i=0; i<n; ++i) { std::cout << c; }
+  std::cout << '\n';
+  mtx.unlock();
+}
+
+int main ()
+{
+  std::thread th1 (print_block,50,'*');
+  std::thread th2 (print_block,50,'$');
+
+  th1.join();
+  th2.join();
+
+  return 0;
+}
\ No newline at end of file
index 1981601..e29e2d4 100644 (file)
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <string>
 #include "TestClass.hpp"
+#include "CallBack.hpp"
 
 using namespace std;
 
index efa4f2a..61dd2e3 100644 (file)
@@ -1,5 +1,9 @@
+#ifndef _TESTCLASS_HPP__
+#define _TESTCLASS_HPP__
+
 #include <iostream>
 #include "TestClassInterface.hpp"
+#include "StructC.hpp"
 
 using namespace std;
 
@@ -19,6 +23,7 @@ class TestClass : public TestClassInterface {
                void                            registerCallback(CallBackInterface* _cb);
                void                            registerCallback(vector<CallBackInterface*> _cb);
                int                                     callBack();
+               void                            handleStruct(vector<data> vecData);
 
        private:                
                int                                                     intA;
@@ -120,6 +125,17 @@ void TestClass::registerCallback(vector<CallBackInterface*> _cb) {
 }
 
 
+void TestClass::handleStruct(vector<data> vecData) {
+
+       for (data dat : vecData) {
+
+               cout << "Name: " << dat.name << endl;
+               cout << "Value: " << dat.value << endl;
+               cout << "Year: " << dat.year << endl;
+       }
+}
+
+
 //int TestClass::callBack() {
 //     return cb.printInt();
 //}
@@ -129,7 +145,20 @@ int TestClass::callBack() {
 
        int sum = 0;
        for (CallBackInterface* cb : cbvec) {
-               sum = sum + cb->printInt();
+               //cout << "Sum: " << sum << endl;
+               //sum = sum + cb->printInt();
+               cb->setInt(sum++);
        }
+       //CallBackInterface* cb = cbvec[0];
+       //sum = cb->printInt();
+       //sum = sum + cb->printInt();
+       //cb->printInt();
+       //CallBackInterface* cb1 = cbvec[0];
+       //cb1->printInt();
+
+
+       return sum;
 }
 
+#endif
+
index 0dd0845..ed73f1e 100644 (file)
@@ -1,7 +1,10 @@
+#ifndef _TESTCLASSINTERFACE_HPP__
+#define _TESTCLASSINTERFACE_HPP__
+
 #include <iostream>
 #include <vector>
-#include "CallBack_CBSkeleton.hpp"
-//#include "CallBack.hpp"
+#include "CallBackInterface.hpp"
+#include "StructC.hpp"
 
 using namespace std;
 
@@ -17,5 +20,8 @@ class TestClassInterface {
                virtual void    registerCallback(CallBackInterface* _cb) = 0;
                virtual void    registerCallback(vector<CallBackInterface*> _cb) = 0;
                virtual int             callBack() = 0;
+               virtual void    handleStruct(vector<data> vecData) = 0;
 };
 
+#endif
+
index 23079c8..665bd16 100644 (file)
@@ -1,16 +1,17 @@
 #include <iostream>
 #include <string>
 #include "TestClass_Skeleton.hpp"
+#include "TestClass.hpp"
 
 using namespace std;
 
 int main(int argc, char *argv[])
 {
 
-       int port = 5010;
+       int port = 5011;
        TestClassInterface *tc = new TestClass(3, 5.0, "7911");
        TestClass_Skeleton *tcSkel = new TestClass_Skeleton(tc, port);
-       tcSkel->waitRequestInvokeMethod();
+       //tcSkel->waitRequestInvokeMethod();
 
        delete tc;
        delete tcSkel;
index 8786e0e..b5452c0 100644 (file)
@@ -1,6 +1,11 @@
+#ifndef _TESTCLASS_SKELETON_HPP__
+#define _TESTCLASS_SKELETON_HPP__
+
 #include <iostream>
 #include "../IoTRMIObject.hpp"
-#include "TestClass.hpp"
+#include "../IoTRMICall.hpp"
+#include "CallBack_CBStub.hpp"
+#include "TestClassInterface.hpp"
 
 using namespace std;
 
@@ -20,13 +25,17 @@ class TestClass_Skeleton : public TestClassInterface {
                void                    registerCallback(CallBackInterface* _cb);
                void                    registerCallback(vector<CallBackInterface*> _cb);
                int                             callBack();
+               void                    handleStruct(vector<data> vecData);
 
-               const static int        size = 9;
+               const static int        size = 12;
                const static string methodSignatures[size];
 
        private:                
-               TestClassInterface              *tc;
-               IoTRMIObject                    *rmiObj;
+               TestClassInterface                      *tc;
+               IoTRMIObject                            *rmiObj;
+               IoTRMICall                                      *rmiCall;
+               static int                                      objIdCnt;
+               vector<CallBackInterface*>      vecCBObj;
                //CallBackInterface cbstub;
 };
 
@@ -41,15 +50,24 @@ const string TestClass_Skeleton::methodSignatures[TestClass_Skeleton::size] = {
        "intsetACAndGetA(string,int)",
        "intcallBack()",
        "voidregisterCallBack(CallBackInterface)",
-       "voidregisterCallBack(CallBackInterface[])"
+       "voidregisterCallBack(CallBackInterface[])",
+       "registercallback",
+       "handleStruct(StructJ[])",
+       "structsize"
 };
 
 
+int TestClass_Skeleton::objIdCnt = 0;
+
+
 TestClass_Skeleton::TestClass_Skeleton(TestClassInterface* _tc, int _port) {
 
        bool _bResult = false;
        tc = _tc;
+       cout << "Reached here 1!" << endl;
        rmiObj = new IoTRMIObject(_port, &_bResult, methodSignatures, size);
+       cout << "Reached here 2!" << endl;
+       waitRequestInvokeMethod();
 }
 
 
@@ -59,11 +77,20 @@ TestClass_Skeleton::~TestClass_Skeleton() {
                delete rmiObj;
                rmiObj = NULL;
        }
+       if (rmiCall != NULL) {
+               delete rmiCall;
+               rmiCall = NULL;
+       }
+       for(CallBackInterface* cb : vecCBObj) {
+               delete cb;
+               cb = NULL;
+       }
 }
 
 
 void TestClass_Skeleton::waitRequestInvokeMethod() {
 
+       int structsize1 = 0;
        // Loop continuously waiting for incoming bytes
        while (true) {
 
@@ -130,11 +157,77 @@ void TestClass_Skeleton::waitRequestInvokeMethod() {
                        void* retObj = &retVal;
                        rmiObj->sendReturnObj(retObj, "int");
                /*} else if (methodSign.compare("voidregisterCallBack(CallBackInterface)") == 0) {
-                       //
-               } else if (methodSign.compare("intcallBack()") == 0) {
                        //*/
+               } else if (methodSign.compare("voidregisterCallBack(CallBackInterface[])") == 0) {
+                       string paramCls[] = { "int" };
+                       int numParam = 1;
+                       int numStubs = 0;
+                       void* paramObj[] = { &numStubs };
+                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
+                       vector<CallBackInterface*> stub;
+                       for (int objId = 0; objId < numStubs; objId++) {
+                               CallBackInterface* cb = new CallBack_CBStub(rmiCall, objIdCnt);
+                               stub.push_back(cb);
+                               vecCBObj.push_back(cb);
+                               objIdCnt++;
+                       }
+                       registerCallback(stub);
+               } else if (methodSign.compare("registercallback") == 0) {
+                       string paramCls[] = { "int", "string", "int" };
+                       int numParam = 3;
+                       int param1 = 0;
+                       string param2 = "";
+                       int param3 = 0;
+                       void* paramObj[] = { &param1, &param2, &param3 };
+                       cout << "Get here! Registering callback!" << endl;
+                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
+                       // Instantiate IoTRMICall object
+                       bool bResult = false;
+                       rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult, 
+                               CallBack_CBStub::methodSignatures, CallBack_CBStub::size);
+               } else if (methodSign.compare("intcallBack()") == 0) {
+                       cout << "Get here inside callback!!!" << endl;
+                       int retVal = callBack();
+                       cout << "Return value in TestClass_Skeleton: " << retVal << endl;
+                       void* retObj = &retVal;
+                       rmiObj->sendReturnObj(retObj, "int");
+               // Handle struct
+               } else if (methodSign.compare("structsize") == 0) {
+                       string paramCls[] = { "int" };
+                       int numParam = 1;
+                       int param1 = 0;
+                       void* paramObj[] = { &param1 };
+                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
+                       structsize1 = param1;
+                       cout << "Struct size: " << structsize1 << endl;
+               } else if (methodSign.compare("handleStruct(StructJ[])") == 0) {
+                       string paramCls[3*structsize1];
+                       void* paramObj[3*structsize1];
+                       int numParam = 3*structsize1;
+                       // define array of everything
+                       string param1[structsize1];
+                       float param2[structsize1];
+                       int param3[structsize1];
+                       int pos = 0;
+                       for(int i=0; i < structsize1; i++) {
+                               paramCls[pos] = "string";
+                               paramObj[pos++] = &param1[i];
+                               paramCls[pos] = "float";
+                               paramObj[pos++] = &param2[i];
+                               paramCls[pos] = "int";
+                               paramObj[pos++] = &param3[i];
+                       }
+                       rmiObj->getMethodParams(paramCls, numParam, paramObj);
+                       vector<data> dat(structsize1);
+                       pos = 0;
+                       for (int i=0; i < structsize1; i++) {
+                               dat[i].name = param1[i];
+                               dat[i].value = param2[i];
+                               dat[i].year = param3[i];
+                       }
+                       handleStruct(dat);
                } else {
-                       string error = "Signature unreqcognized: " + string(methodSign);
+                       string error = "Signature unrecognized: " + string(methodSign);
                        throw error;
                }
        }
@@ -201,3 +294,10 @@ int TestClass_Skeleton::callBack() {
 }
 
 
+void TestClass_Skeleton::handleStruct(vector<data> vecData) {
+
+       tc->handleStruct(vecData);
+}
+
+#endif
+
index 12f47b3..d56d39d 100644 (file)
@@ -1,18 +1,19 @@
 #include <iostream>
 #include <string>
 #include "TestClass_Stub.hpp"
+#include "CallBack.hpp"
 
 using namespace std;
 
 int main(int argc, char *argv[])
 {
 
-       int port = 5010;
+       int port = 5011;
        const char* address = "localhost";
        int rev = 0;
        bool bResult = false;
        vector<int> ports;
-       ports.push_back(12345);
+       ports.push_back(12346);
        //ports.push_back(13234);
 
        TestClassInterface *tcStub = new TestClass_Stub(port, address, rev, &bResult, ports);
@@ -28,8 +29,39 @@ int main(int argc, char *argv[])
        input.push_back(987);*/
 
        cout << "Return value: " << tcStub->sumArray(input) << endl;
+       
+       /*CallBackInterface *cb1 = new CallBack(23);
+       CallBackInterface *cb2 = new CallBack(33);
+       CallBackInterface *cb3 = new CallBack(43);
+       vector<CallBackInterface*> cb;
+       cb.push_back(cb1);
+       cb.push_back(cb2);
+       cb.push_back(cb3);
+       tcStub->registerCallback(cb);
+       cout << "Return value from callback: " << tcStub->callBack() << endl;
 
        delete tcStub;
+       delete cb1;
+       delete cb2;
+       delete cb3;*/
 
+       vector<data> dataset;
+
+       data testdata;
+       testdata.name = "Rahmadi";
+       testdata.value = 0.123;
+       testdata.year = 2016;
+
+       data testdata2;
+       testdata2.name = "Trimananda";
+       testdata2.value = 0.223;
+       testdata2.year = 2017;
+
+       dataset.push_back(testdata);
+       dataset.push_back(testdata2);
+
+       tcStub->handleStruct(dataset);
+
+       delete tcStub;
        return 0;
 }
index 1749a59..39ede87 100644 (file)
@@ -1,7 +1,13 @@
+#ifndef _TESTCLASS_STUB_HPP__
+#define _TESTCLASS_STUB_HPP__
+
 #include <iostream>
+#include <thread>
 #include "../IoTRMICall.hpp"
 #include "../IoTRMIObject.hpp"
 #include "TestClassInterface.hpp"
+#include "CallBack_CBSkeleton.hpp"
+#include "StructC.hpp"
 
 using namespace std;
 
@@ -21,9 +27,11 @@ class TestClass_Stub : public TestClassInterface {
                void                            registerCallback(CallBackInterface* _cb);
                void                            registerCallback(vector<CallBackInterface*>_cb);
                int                                     callBack();
-               void                            init_CallBack();
+               void                            handleStruct(vector<data> vecData);
+               void                            ____init_CallBack();    // thread
+               void                            ____registerCallBack(); // tell the other side that we are ready
 
-               const static int        size = 9;
+               const static int        size = 12;
                const static string methodSignatures[size];
 
        private:                
@@ -35,12 +43,16 @@ class TestClass_Stub : public TestClassInterface {
                IoTRMIObject                            *rmiObj;
                string                                          address;
                vector<int>                                     ports;
-               map<int,CallBackInterface*> mapCBObj;
+               vector<CallBackInterface*>      vecCBObj;
 
                int             objectId = 0;   // Default value is 0
+               static int      objIdCnt;
 };
 
 
+int TestClass_Stub::objIdCnt = 0;
+
+
 const string TestClass_Stub::methodSignatures[TestClass_Stub::size] = {
        "voidsetA(int)",
        "voidsetB(float)",
@@ -51,7 +63,10 @@ const string TestClass_Stub::methodSignatures[TestClass_Stub::size] = {
        "intsetACAndGetA(string,int)",
        "intcallBack()",
        "voidregisterCallBack(CallBackInterface)",
-       "voidregisterCallBack(CallBackInterface[])"
+       "voidregisterCallBack(CallBackInterface[])",
+       "registercallback",
+       "handleStruct(StructJ[])",
+       "structsize"
 };
 
 
@@ -67,6 +82,13 @@ TestClass_Stub::TestClass_Stub(int _port, const char* _address, int _rev, bool*
        address = _address;
        rmiCall = new IoTRMICall(_port, _address, _rev, _bResult, methodSignatures, size);
        ports = _ports;
+       // Start thread
+       cout << "Reached here 1!" << endl;
+//     thread th1 (&TestClass_Stub::____init_CallBack, this);
+//     th1.detach();
+       //th1.join();
+       cout << "Reached here 2!" << endl;
+//     ____registerCallBack();
 }
 
 
@@ -76,21 +98,66 @@ TestClass_Stub::~TestClass_Stub() {
                delete rmiCall;
                rmiCall = NULL;
        }
+       if (rmiObj != NULL) {
+               delete rmiObj;
+               rmiObj = NULL;
+       }
+       for(CallBackInterface* cb : vecCBObj) {
+               delete cb;
+               cb = NULL;
+       }
 }
 
 
 // Callback handler thread
-void TestClass_Stub::init_CallBack() {
+void TestClass_Stub::____init_CallBack() {
 
        bool bResult = false;
+       cout << "Reach here init!" << endl;
        rmiObj = new IoTRMIObject(ports[0], &bResult, CallBack_CBSkeleton::methodSignatures, CallBack_CBSkeleton::size);
+       cout << "Reach here init 2!" << endl;
        while (true) {
                char* method = rmiObj->getMethodBytes();
-               
+               cout << "Get method bytes here: " << endl;
+               IoTRMIUtil::printBytes(method, rmiObj->getMethodBytesLen(), false);
+               int objId = IoTRMIObject::getObjectId(method);
+               if (objId < vecCBObj.size()) {  // Check if still within range
+                       CallBack_CBSkeleton* skel = 
+                               dynamic_cast<CallBack_CBSkeleton*> (vecCBObj.at(objId));
+                       cout << "Dynamic cast done!" << endl;
+                       //rmiObj->setMethodBytes(method);
+                       string type = "";
+                       cout << "About to execute invoke method!" << endl;
+                       void* retObj = skel->invokeMethod(rmiObj, &type);
+                       cout << "Executed invoke method!" << endl;
+                       if (type != "void") {
+                               rmiObj->sendReturnObj(retObj, type);
+                               cout << "Sent return object!" << endl;
+                       }
+               } else {
+                       string error = "TestClass_Stub: Illegal object Id: " + to_string(objId);
+                       throw error;
+               }
        }
 }
 
 
+// Notify that callback thread is ready
+void TestClass_Stub::____registerCallBack() {
+
+       int numParam = 3;
+       string sign = "registercallback";
+       string retType = "void";
+       string paramCls[] = { "int", "string", "int" };
+       int rev = 0;
+       void* paramObj[] = { &ports[0], &address, &rev };
+       void* retObj = NULL;
+       cout << "Get here! 1" << endl;
+       rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
+       cout << "Get here! 2" << endl;
+}
+
+
 void TestClass_Stub::setA(int _int) {
 
        int numParam = 1;
@@ -192,7 +259,19 @@ void TestClass_Stub::registerCallback(CallBackInterface* _cb) {
 
 void TestClass_Stub::registerCallback(vector<CallBackInterface*> _cb) {
 
-       //Should implement the callback here for multiple callback objects
+       for (CallBackInterface* cb: _cb) {
+               CallBack_CBSkeleton* skel = new CallBack_CBSkeleton(cb, objIdCnt++);
+               vecCBObj.push_back(skel);
+       }
+
+       int numParam = 1;
+       string sign = "voidregisterCallBack(CallBackInterface[])";
+       string retType = "void";
+       string paramCls[] = { "int" };
+       int param1 = _cb.size();
+       void* paramObj[] = { &param1 };
+       void* retObj = NULL;
+       rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
 }
 
 
@@ -209,3 +288,36 @@ int TestClass_Stub::callBack() {
        return retVal;
 }
 
+
+void TestClass_Stub::handleStruct(vector<data> vecData) {
+
+       int numParam = 1;
+       string sign = "structsize";
+       string retType = "void";
+       string paramCls[] = { "int" };
+       int structsize = vecData.size();
+       void* paramObj[] = { &structsize };
+       void* retObj = NULL;
+       rmiCall->remoteCall(objectId, sign, retType, paramCls, paramObj, numParam, retObj);
+
+       int numParam2 = 3*vecData.size();
+       string sign2 = "handleStruct(StructJ[])";
+       string retType2 = "void";
+       string paramCls2[numParam2];
+       void* paramObj2[numParam2];
+       int pos = 0;
+       for(int i = 0; i < vecData.size(); i++) {
+               paramCls2[pos] = "string";
+               paramObj2[pos] = &vecData[i].name; pos++;
+               paramCls2[pos] = "float";
+               paramObj2[pos] = &vecData[i].value; pos++;
+               paramCls2[pos] = "int";
+               paramObj2[pos] = &vecData[i].year; pos++;
+       }
+       void* retObj2 = NULL;
+       cout << "In handle struct 3!" << endl;
+       rmiCall->remoteCall(objectId, sign2, retType2, paramCls2, paramObj2, numParam2, retObj2);
+}
+
+
+#endif
diff --git a/iotjava/iotrmi/Java/sample/StructJ.java b/iotjava/iotrmi/Java/sample/StructJ.java
new file mode 100644 (file)
index 0000000..b1a0354
--- /dev/null
@@ -0,0 +1,8 @@
+package iotrmi.Java.sample;
+
+public class StructJ {
+
+       public static String name;
+       public static float value;
+       public static int year;
+}
diff --git a/iotjava/iotrmi/Java/sample/StructMain.java b/iotjava/iotrmi/Java/sample/StructMain.java
new file mode 100644 (file)
index 0000000..3f4456c
--- /dev/null
@@ -0,0 +1,17 @@
+package iotrmi.Java.sample;
+
+public class StructMain {
+
+       public static void main (String[] args) {
+
+               StructJ data = new StructJ();
+               data.name = "Rahmadi";
+               data.value = 0.123f;
+               data.year = 2016;
+
+               System.out.println("Name: " + data.name);
+               System.out.println("Value: " + data.value);
+               System.out.println("Year: " + data.year);
+       }
+}
+
index 1c95b3a..a59518a 100644 (file)
@@ -145,13 +145,22 @@ public class TestClass implements TestClassInterface {
                return sum;
        }
 
+       public void handleStruct(StructJ[] data) {
+
+               for (StructJ str : data) {
+                       System.out.println("Name: " + str.name);
+                       System.out.println("Value: " + str.value);
+                       System.out.println("Year: " + str.year);
+               }
+       }
+
 
        public static void main(String[] args) {
 
-               TestClass tc = new TestClass();
-               CallBack cb = new CallBack(3);
+               //TestClass tc = new TestClass();
+               //CallBack cb = new CallBack(3);
 
-               tc.registerCallback(cb);
-               System.out.println("Return value: " + tc.callBack());
+               //tc.registerCallback(cb);
+               //System.out.println("Return value: " + tc.callBack());
        }
 }
index b9c563a..9d46df5 100644 (file)
@@ -13,4 +13,5 @@ public interface TestClassInterface {
        public void registerCallback(CallBackInterface _cb);
        public void registerCallback(CallBackInterface[] _cb);
        public int callBack();
+       public void handleStruct(StructJ[] data);
 }
index 10f136d..3435959 100644 (file)
@@ -27,7 +27,8 @@ public class TestClass_CBSkeleton implements TestClassInterface {
                "intcallBack()",
                "voidregisterCallBack(CallBackInterface)",
                "voidregisterCallBack(CallBackInterface[])",
-               "registercallback"
+               "registercallback",
+               "handleStruct(StructJ)"
        };
 
        private TestClassInterface tc;
@@ -169,6 +170,11 @@ public class TestClass_CBSkeleton implements TestClassInterface {
                return tc.callBack();
        }
 
+       public void handleStruct(StructJ[] data) {
+
+               tc.handleStruct(data);
+       }
+
 
        public static void main(String[] args) throws Exception {
 
index 65550c7..a3d80fd 100644 (file)
@@ -38,7 +38,8 @@ public class TestClass_CBStub implements TestClassInterface {
                "intcallBack()",
                "voidregisterCallBack(CallBackInterface)",
                "voidregisterCallBack(CallBackInterface[])",
-               "registercallback"
+               "registercallback",
+               "handleStruct(StructJ)"
        };
 
        /**
@@ -236,6 +237,10 @@ public class TestClass_CBStub implements TestClassInterface {
 
        }
 
+       public void handleStruct(StructJ[] data) {
+
+       }
+
 
        public static void main(String[] args) throws Exception {
 
index acab4ac..a115615 100644 (file)
@@ -27,7 +27,9 @@ public class TestClass_Skeleton implements TestClassInterface {
                "intcallBack()",
                "voidregisterCallBack(CallBackInterface)",
                "voidregisterCallBack(CallBackInterface[])",
-               "registercallback"
+               "registercallback",
+               "handleStruct(StructJ[])",
+               "structsize"
        };
 
        private TestClassInterface tc;
@@ -53,6 +55,8 @@ public class TestClass_Skeleton implements TestClassInterface {
 
        public void waitRequestInvokeMethod() throws IOException {
 
+               // Struct size
+               int structsize1 = 0;
                // Loop continuously waiting for incoming bytes
                while (true) {
 
@@ -114,6 +118,40 @@ public class TestClass_Skeleton implements TestClassInterface {
                                        String[] methodSignatures = CallBack_CBStub.getMethodSignatures();
                                        rmiCall = new IoTRMICall((int) paramObj[0], (String) paramObj[1], (int) paramObj[2], methodSignatures);
                                        System.out.println("Creating a new IoTRMICall object");
+                               // Struct handling (3 is the size of the struct)
+                               } else if (methodSign.equals("structsize")) {
+                                       paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, 
+                                               new Class<?>[] { null }, new Class<?>[] { null });
+                                       structsize1 = (int) paramObj[0];
+                               } else if (methodSign.equals("handleStruct(StructJ[])")) {
+                                       Class<?>[] paramCls = new Class<?>[3*structsize1];
+                                       Class<?>[] paramClsTyp1 = new Class<?>[3*structsize1];
+                                       Class<?>[] paramClsTyp2 = new Class<?>[3*structsize1];
+                                       int pos = 0;
+                                       for(int i=0; i < structsize1; i++) {
+                                               paramCls[pos] = String.class;
+                                               paramClsTyp1[pos] = null;
+                                               paramClsTyp2[pos++] = null;
+                                               paramCls[pos] = float.class;
+                                               paramClsTyp1[pos] = null;
+                                               paramClsTyp2[pos++] = null;
+                                               paramCls[pos] = int.class;
+                                               paramClsTyp1[pos] = null;
+                                               paramClsTyp2[pos++] = null;
+                                       }
+                                       paramObj = rmiObj.getMethodParams(paramCls, 
+                                               paramClsTyp1, paramClsTyp2);
+                                       StructJ[] data = new StructJ[structsize1];
+                                       for (int i=0; i < structsize1; i++) {
+                                               data[i] = new StructJ();
+                                       }
+                                       pos = 0;
+                                       for(int i=0; i < structsize1; i++) {
+                                               data[i].name = (String) paramObj[pos++];
+                                               data[i].value = (float) paramObj[pos++];
+                                               data[i].year = (int) paramObj[pos++];
+                                       }
+                                       tc.handleStruct(data);
                                } else
                                        throw new Error("Signature not recognized!");
 
@@ -184,6 +222,11 @@ public class TestClass_Skeleton implements TestClassInterface {
                return tc.callBack();
        }
 
+       public void handleStruct(StructJ[] data) {
+
+               tc.handleStruct(data);
+       }
+
 
        public static void main(String[] args) throws Exception {
 
index 90e2264..43fcaf0 100644 (file)
@@ -38,7 +38,9 @@ public class TestClass_Stub implements TestClassInterface {
                "intcallBack()",
                "voidregisterCallBack(CallBackInterface)",
                "voidregisterCallBack(CallBackInterface[])",
-               "registercallback"
+               "registercallback",
+               "handleStruct(StructJ[])",
+               "structsize"
        };
 
        /**
@@ -101,7 +103,7 @@ public class TestClass_Stub implements TestClassInterface {
 
                String sign = "registercallback";       // can be any string
                Class<?> retType = void.class;
-               // port, address, rev, and number of objects
+               // port, address, rev
                Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };
                Object[] paramObj = new Object[] { ports[0], address, 0 };
                rmiCall.remoteCall(objectId, sign, retType, null, null, paramCls, paramObj);
@@ -230,6 +232,34 @@ public class TestClass_Stub implements TestClassInterface {
        }
 
 
+       public void handleStruct(StructJ[] data) {
+
+               String sign = "structsize";
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { int.class };
+               Object[] paramObj = new Object[] { data.length };
+               rmiCall.remoteCall(objectId, sign, retType, null, null, paramCls, paramObj);
+
+               String sign2 = "handleStruct(StructJ[])";
+               Class<?> retType2 = void.class;
+               // Calculate the size of the array
+               Class<?>[] paramCls2 = new Class<?>[3*data.length];
+               Object[] paramObj2 = new Object[3*data.length];
+               // Handle with for loop
+               int pos = 0;
+               for(int i = 0; i < data.length; i++) {
+                       paramCls2[pos] = String.class;
+                       paramObj2[pos++] = data[i].name;
+                       paramCls2[pos] = float.class;
+                       paramObj2[pos++] = data[i].value;
+                       paramCls2[pos] = int.class;
+                       paramObj2[pos++] = data[i].year;
+               }
+               System.out.println(Arrays.toString(paramObj2));
+               rmiCall.remoteCall(objectId, sign2, retType2, null, null, paramCls2, paramObj2);
+       }
+
+
        public static void main(String[] args) throws Exception {
 
                CommunicationHandler comHan = new CommunicationHandler(true);
@@ -247,7 +277,7 @@ public class TestClass_Stub implements TestClassInterface {
                System.out.println("Return value: " + tcstub.setACAndGetA("string", 123));
                System.out.println("Return value: " + tcstub.sumArray(new String[] { "123", "456", "987" }));
 
-               CallBackInterface cb1 = new CallBack(23);
+               /*CallBackInterface cb1 = new CallBack(23);
                CallBackInterface cb2 = new CallBack(33);
                CallBackInterface cb3 = new CallBack(43);
                CallBackInterface[] cb = { cb1, cb2, cb3 };
@@ -258,7 +288,26 @@ public class TestClass_Stub implements TestClassInterface {
                CallBackInterface cb6 = new CallBack(12);
                CallBackInterface[] cbt = { cb4, cb5, cb6 };
                tcstub.registerCallback(cbt);
-               System.out.println("Return value from callback: " + tcstub.callBack());
+               System.out.println("Return value from callback: " + tcstub.callBack());*/
+
+               StructJ[] data = new StructJ[2];
+               for (int i=0; i<2; i++) {
+                       data[i] = new StructJ();
+               }
+               data[0].name = "Rahmadi";
+               data[0].value = 0.123f;
+               data[0].year = 2016;
+               //data[1].name = "Trimananda";
+               //data[1].value = 0.223f;
+               //data[1].year = 2017;
+
+               for (StructJ str : data) {
+                       System.out.println("Name: " + str.name);
+                       System.out.println("Value: " + str.value);
+                       System.out.println("Year: " + str.year);
+               }
+
+               tcstub.handleStruct(data);
        }
 }