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;
};