RMI의 파라메터에 사용자 정의 객체 타입을 넣는 방법은 PIDL 파라메터 타입 다루기(마샬링)에 나와있습니다. C# 언어 또한 이것이 가능합니다.
C++ 쪽에서의 CFastArray를 serializing해서 보냈을 때에 C# 쪽에서 이를 받아 deserializing하여 사용하는 방법을 예로 들어서 설명해드리도록 하겠습니다.
설명은 아래에 나와있는 5 단계로 진행됩니다.
C# Student 클래스 작성
C++ CStudent 클래스 작성
PIDL 작성
C++ 마샬링 코드 작성
C# 마샬링 코드 작성
본 설명에서 작성해보는 간략한 예제는 C# 클라이언트에서 Ping 라는 RMI를 호출하면, 그것을 받은 C++ 서버는 StudentList RMI를 호출하여 C++의 CFastArray를 C# 쪽으로 전달하게 되고, C# 쪽은 그것을 List로 전달받는 예제입니다.
18.1C# Student 클래스
namespace CsClient{class Student{public string Name;public int ID;public int Kor;public int Eng;public int Mat;public override string ToString(){return string.Format("Name: {0}({1}) K: {2}, E: {3}, M: {4}", Name, ID, Kor, Eng, Mat);}}}
C#쪽 클라이언트에서 사용될 클래스입니다.
18.2C++ CStudent 클래스 작성
class CStudent{public:String Name;int ID;int Kor;int Eng;int Mat;};
C++쪽 서버에서 사용될 클래스입니다.
18.3PIDL 작성
rename cs(Proud::CFastArray<CStudent>, System.Collections.Generic.List<CsClient.Student>);[marshaler(cs)=CsClient.MyMarshaler]global S2C 3000{StudentList([in] Proud::CFastArray<CStudent> students);}
Line1: rename 키워드는 서로 다른 언어간의 PIDL 통신에 사용됩니다. 이름은 Namespace를 포함해야 합니다.
Line2: marshaler(cs) 키워드로 C#쪽에서 사용될 마샬러를 지정합니다. 이름은 Namespace를 포함해야 합니다.
Line5: StudentList PIDL을 생성합니다. 기본적으로 C++쪽에서 사용하시듯 작성하시면 됩니다.
C2S.PIDL
[marshaler(cs)=CsClient.MyMarshaler]global C2S 4000{Ping([in] int value);}
이 예제 PIDL 코드는 클라이언트에서 Ping을 보내면 StudentList를 보내주는 PIDL 코드입니다.
해당 파일을 빌드하셔서 .h, .cpp, .cs 파일을 생성합니다.
18.4C++ 마샬링 코드 작성
namespace Proud{CMessage& operator >> (CMessage& msg, CStudent student){msg >> student.Name >> student.ID >> student.Kor >> student.Eng >> student.Mat;return msg;}CMessage& operator << (CMessage& msg, const CStudent& student){msg << student.Name << student.ID << student.Kor << student.Eng << student.Mat;return msg;}}
예제로 만들어진 CStudent클래스를 마샬링하는 코드입니다.
더 자세한 정보는 http://guide.nettention.com/cpp_ko#collection_marshal 링크를 참조해 주십시오.
C2SStub
class C2SStub : public C2S::Stub{public:DECRMI_C2S_Ping;};DEFRMI_C2S_Ping(C2SStub){{CriticalSectionLock(g_lock, true);g_S2CProxy.StudentList(remote, RmiContext::ReliableSend, g_Students);}return true;}C2SStub g_C2SStub;
C# 클라이언트에서 Ping을 보내오면 StudentList를 보내주는 코드입니다.
18.5C# 마샬링 코드 작성
namespace CsClient{class MyMarshaler : Nettention.Proud.Marshaler{public static bool Read(Message msg, out List<Student> students){students = null;if (!msg.ReadScalar(out var size)){return false;}students = new List<Student>();for (int i = 0; i < size; ++i){Student s = new Student();if (!msg.Read(out s.Name)) { return false;}if (!msg.Read(out s.ID)){return false;}if (!msg.Read(out s.Kor)){return false;}if (!msg.Read(out s.Eng)){return false;}if (!msg.Read(out s.Mat)){return false;}students.Add(s);}return true;}public static void Write(Message msg, List<Student> students){msg.WriteScalar(students.Count);for (int i = 0; i < students.Count; ++i){msg.Write(students[i].Name);msg.Write(students[i].ID);msg.Write(students[i].Kor);msg.Write(students[i].Eng);msg.Write(students[i].Mat);}}}}
C#의 마샬링은 Nettention.Proud.Marshaler을 상속받아 구현한 뒤, 대체하는 방식으로 개발됩니다.
대체는 직접 하실 필요없이 PIDL에 선언한 [marshaler(cs)=CsClient.MyMarshaler] 키워드로 동작합니다.
g_S2CStub.StudentList = (remote, rmiContext, students) =>{lock(g_lock){// List<Student> 로 넘어오는 students를 사용하시면 됩니다.foreach (var s in students){Console.WriteLine(s.ToString());}}return true;};