serialize/deserialize user defined class variable? - serialization

Suppose I have two classes:
class1 {
int m_i;
std::string m_s;
};
class2 {
int m_i2;
class1 *m_ptr;
};
Now, I want to send a class2 variable over network, and want to use any of the libraries that does serialization.(Protocol-buffers, Thrift, MessagePack..)
Which one can I use?(note the class1* m_ptr)

You could use thrift for this.
the definition would look something like
struct class1 {
1: required i32 m_i;
2: required string m_s;
}
struct class2 {
1: required i32 m_i2;
2: optional class1 m_ptr;
}
You would like to read this excellent guide
http://diwakergupta.github.com/thrift-missing-guide/
and to get clarity on concern about the "pointer" issue that you mentioned in the question,read the section on "How are nested structs initialized?" in the above guide.

Using google protocol buffers, you would need a .proto file (say test.proto) like:
package serialisation; // puts this in namespace serialisation
message class1 {
required int32 m_i = 1;
required bytes m_s = 2;
}
message class2 {
required int32 m_i2 = 1;
optional class1 m_ptr = 2;
}
Using C++, once you run the protoc compiler against this, you end up with test.pb.cc and test.pb.h
You can then use these like:
#include <string>
#include "test.pb.h"
struct class1 {
int m_i;
std::string m_s;
};
struct class2 {
int m_i2;
class1 *m_ptr;
};
int main() {
class2 second_class;
second_class.m_i2 = 2;
second_class.m_ptr = new class1;
second_class.m_ptr->m_i = 1;
second_class.m_ptr->m_s = "one";
// Serialise class 2
serialisation::class2 serialisable_second_class;
serialisable_second_class.set_m_i2(second_class.m_i2);
if (second_class.m_ptr) {
serialisation::class1* serialisable_first_class = serialisable_second_class.mutable_m_ptr();
serialisable_first_class->set_m_i(second_class.m_ptr->m_i);
serialisable_first_class->set_m_s(second_class.m_ptr->m_s);
}
std::string serialised(serialisable_second_class.SerializeAsString());
// Parse class 2
serialisation::class2 parsed_second_class;
parsed_second_class.ParseFromString(serialised);
class2 retrieved_second_class;
retrieved_second_class.m_i2 = parsed_second_class.m_i2();
if (parsed_second_class.has_m_ptr()) {
retrieved_second_class.m_ptr = new class1;
retrieved_second_class.m_ptr->m_i = parsed_second_class.m_ptr().m_i();
retrieved_second_class.m_ptr->m_s = parsed_second_class.m_ptr().m_s();
} else {
retrieved_second_class.m_ptr = nullptr;
}
return 0;
}
Note, for the sake of brevity I'm not doing any error checking or exception handling here - this would be needed in production code. I'm also not managing the lifetime of the class1 pointer.

Related

private data member in C++ OOP

I am new to OOP in C++. I got a doubt. I know it may be a silly doubt.
In the code below in main function, commented line will give error as I can not access private data memebers directly. but in the member function complex add(complex &C) I created a object temp of class complex. How can I access the data member of object temp directly and modify them as those are private. Like in the main function, should it not throw error? Is there any rule that in the member function of class we can access private data of a object of same class directly.
using namespace std;
class complex{
private:
int real;
int img;
public:
complex(int r = 0, int i = 0);
complex add(complex &C);
};
complex :: complex(int r, int i){
real = r;
img = i;
}
complex complex :: add(complex &C){
complex temp;
temp.real = real + C.real;
temp.img = img + C.img;
return temp;
}
int main() {
complex c1(3,4);
complex c2(5,7);
complex c3;
// c3.real = 3;
// c3.img = 5;
c3 = c1.add(c2);
return 0;
}
I try and stick to rule, keep your member variables private, if you need to change them or access them once the object is created, use a public get / set function.
e.g:
int complex::GetReal() const { return m_real; }
void complex::SetReal(const int i) { m_real = i; }

No suitable conversion function from [class name] to [class name]*

I am new to c++/cli, the situation I faced is that:
the project I am doing needs to use an external dll, in my functions I need to use classes A, B and C which are from this dll, I put them in my .h file, the .h file looking like:
#include library I use
public ref class MyClass
{
public:
MyClass();
~MyClass();
otherfuc();
private:
A *a;
B *b;
C *c;
}
My .cpp file looking like:
MyClass::MyClass()
{
a = new A();
b = new B(*a);
c = b->func(); //error happened
}
MyClass::otherfunc()
{
c->func_c()
}
Class A, B, C are unmanaged class, so I only have one way to declare them in managed class, just like I do in the header file. In class B, it has a function which is called func, this function return class type C, I tried c = &b->func(), in this way, it will throw AccessViolationException, if I tried c = b->func, then the error is function call missing argument. What should I do, please help!!!
From what you've written my guess is that B::func() is declared to return a C instance as a temporary:
class B {
public:
C func();
};
Allocate an instance of C as a copy of temporary:
class A {
};
class C {
public:
C(int _i) : i(_i) {}
int func_c() { return i; }
int i;
};
class B {
public:
B(A & a) {}
C func() { return C(5); }
};
public ref class MyClass {
public:
MyClass();
~MyClass();
int otherfunc();
private:
A *a;
B *b;
C *c;
};
MyClass::MyClass()
{
a = new A();
b = new B(*a);
c = new C(b->func());
}
MyClass::~MyClass() {
delete a;
delete b;
delete c;
}
int MyClass::otherfunc()
{
return c->func_c();
}
void f() {
MyClass^ mc = gcnew MyClass();
int i = mc->otherfunc();
}
This assumes C is copyable (or moveable) and that copying it make sense for what you are doing.

How do i copy to a List?

I have this code in CLI
List<Codec^> ^GetCodecs()
{
List<Codec^> ^l = gcnew List<Codec^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
Codec ^codec = gcnew Codec(); // here... and that call encoder_init many times... which call register codec many times... which is a mass...
codec->Name = gcnew String(Encoder_GetCurrentCodecName());
codec->Type = Encoder_GetCurrentCodecType();
char pix_fmts[200]; // array of 200 is probably enough
int actual_pix_fmts_sz = Encoder_GetCurrentCodecPixFmts( pix_fmts , 200 );
for (int i = 0 ; i < actual_pix_fmts_sz ; i++)
{
//copy from pix_fmts to the :List
codec->SupportedPixelFormats->Add(pix_fmts[i]);
}
This is the Encoder_GetCurrentCodecPixFmts function in C:
int Encoder_GetCurrentCodecPixFmts( char *outbuf , int buf_sz )
{
int i=0;
while ( (i<buf_sz) && (codec->pix_fmts[i]!=-1) )
{
outbuf[i] = codec->pix_fmts[i];
i++;
}
return i;
}
This is a new class i did:
#pragma once
using namespace System;
using namespace System::Collections::Generic;
public ref class Codec
{
public:
String^ Name;
int ID; // this is the index
int Type; // this is the type
List<int> ^SupportedPixelFormats;
Codec(void)
{
SupportedPixelFormats = gcnew List<int>;
// do nothing in the constructor;
}
};
Which contain also the: SupportedPixelFormats
The constructor in this new class should be empty but i needed somewhere to make an instance for the List make a NEW for the List.
Now in the C++ i need to transfer from pix_fmts char array to codec->Supported
Or to copy from pix_fmts to the :List
So i did as above:
codec->SupportedPixelFormats->Add(pix_fmts[i]);
But i'm not sure if this the meaning of copy.
Is that right what i did ?
It works, it's a kind of a deep copy. What makes you think it doesn't work? Do the results turn out wrong? If they do, put a breakpoint in there and try to get what is wrong.
Instead of copying one by one perhaps you can use the Enumerable::ToList extension method.
I hope this helped you.

Make sort using delegates

I'm try to make a sort delegate in C++/CLI, but, when I try to compile I recive this erro:
>app.cpp(256): error C3374: can't take address of 'Program::AnonymousMethod1' unless creating delegate instance
>app.cpp(256): error C2664: 'void System::Collections::Generic::List<T>::Sort(System::Comparison<T> ^)' : cannot convert parameter 1 from 'System::Object ^(__clrcall *)(Program::teste1,Program::teste1)' to 'System::Comparison<T> ^'
> with
> [
> T=Program::teste1 ^
> ]
> No user-defined-conversion operator available, or
> There is no context in which this conversion is possible
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
here is the code sample of the error:
using namespace System;
using namespace System::Collections::Generic;
private ref class Program
{
private:
enum class tokens
{
teste,
lala,
blabla,
};
ref struct teste1
{
int linha;
tokens tk;
};
private:
static Object ^AnonymousMethod1(teste1 p1, teste1 p2)
{
return p1.tk.CompareTo(p2.tk);
}
public:
Program()
{
bool jump = false;
List<teste1^>^ lstTest = gcnew List<teste1^>();
Random ^rnd = gcnew Random();
for (int i = 0; i < 20; i++)
{
teste1 ^tst = gcnew teste1();
switch (rnd->Next(1,4))
{
case 1:
tst->tk = tokens::teste;
break;
case 2:
tst->tk = tokens::lala;
break;
case 3:
tst->tk = tokens::blabla;
break;
}
lstTest->Add(tst);
}
for each (teste1^ content in lstTest)
{
Console::WriteLine(content->tk.ToString());
}
lstTest->Sort(AnonymousMethod1);
Console::WriteLine("==============================================================");
for each (teste1^ content in lstTest)
{
Console::WriteLine(content->tk.ToString());
}
}
};
int main(array<String^> ^args)
{
Program^ prg = gcnew Program();
return 0;
}
I just whant to sort the list with the token 'lala' first, how I can make this, and, How I can solve this ???
Your List is of type List<test1^> (notice the ^ hat). So the Comparison<T> delegate you want is Comparison<teste1^>. Thus you'll want to change your AnonymousMethod1 as follows:
static int AnonymousMethod1(teste1 ^ p1, teste1 ^ p2)
{
return p1->tk.CompareTo(p2->tk);
}
And in C++/CLI you need to explicitly create your delegate:
Comparison<teste1 ^> ^ comparisonDelegate = gcnew Comparison<teste1 ^>(&AnonymousMethod1);
lstTest->Sort(comparisonDelegate);

Class based on wxObject fails to link

First, this is being built on Linux.
We have an API that is based on wxObjects (we do not use the GUI objects). Our classes are defined as follows:
#include <wx/wx.h>
class apibaseclass : public wxObject
{
apibaseclass();
~apibaseclass();
}
About five years ago this compiled and linked just fine. I've been asked to make changes and now I get the following error:
undefined reference to wxObject::wxObject()'/home/lloyd/Projects/wxtestprogram/main.cpp:7: undefined reference towxObject::wxObject()'
This is the program I was using as a sanity test:
#include <iostream>
#include <wx/wx.h>
class blah : public wxObject
{
public:
int x;
blah();
virtual ~blah();
void setvalue(int value);
int getvalue();
};
blah::blah()
{
}
blah::~blah()
{
}
void blah::setvalue(int value)
{
x = value;
}
int blah::getvalue()
{
return x;
}
using namespace std;
int main()
{
class blah *testvalue = new blah();
testvalue->setvalue(15);
wxPrintf(wxT("Hello World 2 %d\r\n"), testvalue->getvalue());
wxString str1 = wxT("Linux");
wxString str2 = wxT("Operating");
wxString str3 = wxT("System");
wxString str;
str = str1 + wxT(" ") + str2 + wxT(" ") + str3;
wxPuts(str);
wxPrintf(wxGetHomeDir());
long int mem = wxGetFreeMemory();
wxPrintf(wxT("Memory: %ld\n"), mem);
return 0;
}
What is bothersome is that if I replace "public wxObject" with "public wxString" then it links just fine. Why am I unable to access wxObject?!?
NOTE: I've never linked against anything other than libwx_baseu-2.6.so in the past. And in fact when I build without the GUI it only builds libwx_baseu-2.6, libwx_baseu_net-2.6 and libwx_baseu_xml-2.6.
What do I need to do to get things building and LINKING again with minimal muss and fuss?
Using
wx-config --cxxflags --libs base
gave me the missing items that allowed me to build the project correctly. No doubt this is what I used five years ago.