The usage of RMI in ProudNet is as followed.
11.1Making a PIDL file
In order to use Remote Method Invocation(RMI) from ProudNet, you need to create a file with extension PIDL.
PIDL file is a source file that defines messages being exchanged between hosts. When you compile this PIDL file, proxy and stub will get generated. We are going to include these proxy and stub in host program. More details on proxy and stub can be found from 4. Remote Method Invocation.
The basic format of using PIDL file is as followed.
Warning!! Do not use the value between 0 and 1300 & 60000 and 70000 as the first ID value of a message. It already used for ID parameter of ProudNet internal PIDL. If message ID is the same, exception will occur from AttachProxy and AttachStub function.
global <NameSpace> <The first ID value of message> { ([Characteristic declaration]) <Function declaration> ( [in] Function parameter, ... ); }
Here are the detailed descriptions for above.
NameSpace: It's a name of C++ namespace that proxy and stub module get when they are generated by compiling PIDL file. ProudNet can use more 2 of proxy and stub simultaneously but to avoid any conflict they need namespace. For instance, if you declare as LobbyC2S, it would refer to ‘declare server call RMI of Client -> Server from game lobby'.
The first ID value of message : When RMIS are called, each RMI converts to network message, which contains ID value in their header. This ID is called the first ID value of message. One thing you need to be careful about is that since there can be several proxy and stub, the range of each message ID must not overwrap. Please refer to 16. The range of message for RMI for more details.
Characteristic declaration : Please refer to below.
Function declaration : Name of RMI function
Function Parameter : It's similar to C++ function declaration. You must declare [in] first. Parameters can allow declarations as followed, except pointer type.
int a std::vector<int> b CString c
Function parameter can use not only the basic type such as int, but also object defined by developer. Please refer to marshaling for more details.
Example for PIDL file is as followed.
global LobbyC2S 5000 // Message ID starts from 5000 { Logon([in] CString name,[in] CString password); // ID=5001 RequestRoomList([in] int pageNumber); // ID=5002 Chat([in] CString name); // ID=5003 }
Reference
• 19.2 Communicating between programs written in other languages than C# and C++
11.2How to run PIDL Compiler
1. How to run PIDL Compiler on Linux
Install open source Momo Project on Ubuntu (※ Mono Project supports Linux, Windows, Mac OS all.)
$sudo apt-get install mono-gmcs $sudo apt-get install mono-runtime
Install open source Momo Project on CentOS (※ Mono Project supports Linux, Windows, Mac OS all.)
$sudo yum install mono-devel $sudo yum install mono-complete
Run PIDL Compiler on Mono Platform
$pwd /home/ProudNet/util $mono PIDL.exe ../Sample/Simple/Common/*.pidl -outdir ./
How to run PIDL Compiler on Windows
• Setup PIDL Custom Build on Visual Studio Project
The details of build setting are as followed.
- Command line: <Path where holding PIDL.exe>\PIDL.exe "%(FullPath)" -outdir .\
- Description: Compiling %(Filename).pidl ...
- Output: %(RootDir)%(Directory)\%(Filename)_common.cpp;%(RootDir)%(Directory)\%(Filename)_common.h;%(RootDir)%(Directory)\%(Filename)_proxy.cpp;%(RootDir)%(Directory)\%(Filename)_proxy.h;%(RootDir)%(Directory)\%(Filename)_stub.cpp;%(RootDir)%(Directory)\%(Filename)_stub.h;%(Outputs)
- Additional dependency: <Path where holding PIDL.exe>\PIDL.exe
There are few things you need to be aware of.
PIDL.exe is included in util folder of ProudNet(Example: C:/Program Files/Nettention/ProudNet/util/pidl.exe)
The settings of Debug and Release build must be identical!
When you are done with settings, try to compile PIDL file. You are supposed to get the following messages if the compile is succeeded.
1>------ Build begin: Project: ..., Configuration: Release Win32 ------ 1>Compiling TestC2C.pidl ... 1>Build log has been saved to "...". 1>ProudNetTest_2005 - Error: 0, Warning: 0 ========== Build: Success 1, Fail 0, Recent 0, Skip 0 ==========
Visual Studio 2005 and 2008 version support Custom Build Rules.
If you use it, it automatically apply setting when you add PIDL files.
In case of a version starting with Visual Studio 2010, Build customizations can be used.
Custom Build Rules use.
You can make Custom Build Rule by using Custom Build Rules at Visual Studio 2005 and 2008.
If clicking "New Rule File..." from UI that is shown when clicking Custom Build Rules, you will be able to make a rule file.
Display Name: it is the name shown at Custom Build Rules. ex) PIDL Rule
File Name: Specify a name. ex) PIDL_Custom_Build_Rule
Directory: set the directory in which the rule file will be saved. ex) PIDL Rule
If clicking "Add Build Rule..." , you will be able to make a new rule.
The detailed information of setting is as below.
Additional Dependencies : ..\..\..\util\PIDL.exe Batching Separator : Command Line : ..\..\..\util\PIDL.exe "$(InputPath)" -outdir .\ Display Name : PIDL Execution Description : Compiling $(InputName).pidl ... File Extensions : *.pidl Name : PIDL Custom Build Rule Outputs : $(InputDir)\$(InputName)_common.cpp;$(InputDir)\$(InputName)_common.h;$(InputDir)\$(InputName)_proxy.cpp;$(InputDir)\$(InputName)_proxy.h;$(InputDir)\$(InputName)_stub.cpp;$(InputDir)\$(InputName)_stub.h
Once the relevant setting is completed, PIDL Build Rule will be added as below.
Check the rule file that has been newly made. And if making a file at the relevant project, you will be able to check Build Tool has been automatically selected.
customizations use.
You can make a rule file by using Custom Build Rules in case of Visual Studio 2005 and 2008.
In case of a version starting with Visual Studio 2010, you can use a rule file but UI that writes the rule file is removed.
The rule file used at Visaul Studio 2005 and 2008 is 1 file whose extension is .rules but in case of a version starting with Visaul Studio 2010, 3 files whose extensions are .props, .targets and .xml will be required. As a result of this, you cannot use .rules files made at Visual Studio 2005 and 2008.
In order to use customizations at a version starting with Visaul Studio 2010, you are allowed to select one of the following 2 ways.
Create a project at Visual Studio 2005 or 2008 and then make .rules files & do the relevant settings. After that, convert the project into the version starting with 2010.
Create .props, .targets and .xml files and then write a xml code directly.
In case of converting the project, .rules files will be created right after being automatically converted as .props, .targets and .xml.
Defined macro at Visual Studio 2005, 2008 and starting with Visual Studio 2010 is different. If the relevant rule is not written by a macro used at a version starting with Visaul Studio 2010, you will need to convert the macro mentioned before to the macro used at a version starting with Visaul Studio 2010 before converting or you will need to modify .props, .targets and .xml respectively.
11.3Attaching RMI proxy and stub
Class name of PIDL compiled result
Class name of proxy and stub generated through PIDL file are the classes named as Proxy and Stub of namespace designated from PIDL. For instance, if you refer to PIDL file below
global TestC2S { ... };
Proxy and stub that get generated by this code become TestC2S. Proxy and TestC2S.Stub.
PIDL file name of compiled result
First, the generated source file must be included in PIDL file. For example, if you’ve compiled TestC2S.PIDL, the name of generated Proxy module becomes TestC2S_Proxy.h. And the name of Stub module becomes TestC2S_Stub.cpp, TestC2S_Stub.h.
It is not suggested to directly attach Proxy or Stub to a project under development. Even through the compiled result of PIDL file is only a text file made of C++ language, it is still a compiled result. If you are using any source control and your compiled result is for read only then it may cause a trouble.
Thus it is better to include them by using #include.
Attaching Proxy to client and server
First, you need to generate Proxy instance of PIDL compiled result. And then, you need to register the instance to Proud.CNetClient or Proud.CNetServer.
Client and server inherit Proud.IRmiHost and Proxy can be registered through the included method, Proud.IRmiHost.AttachProxy.
Each client and server can be attached with more than two of Proxy as long as the range of message ID doesn't overwrap with each other. Let's assume there is TestA.Proxy already attached in CNetClient and you want to additionally attach TestB.Proxy. And you declared the first message ID of TestA as 2100 and TestB as 2200. If the number of RMI functions declared by TestA is 200, then the range of TestA message ID becomes 2100~2300, which overwraps with the ID of TestB. When this happens, an exception will be thrown.
Attaching Stub to client and server
If you are using C++11, check out another way described below.
The stub instance of PIDL compiled result contains RMI functions that will be run by messages sent through network as virtual function. You need to inherit this Stub class and override RMI functions.
For your convenience, PIDL Compiler (ProudNet IDL) generated macros as followed. These macros are wrapped with RMI function name and parameter.
#define DECRMI_S2C_ShowChat bool ShowChat(Proud::HostID remote,Proud::RmiContext &rmiContext,const CString &a,const int &b,const float &c) #define DEFRMI_S2C_ShowChat(DerivedClass) bool DerivedClass::ShowChat(Proud::HostID remote,Proud::RmiContext &rmiContext,const CString &a,const int &b,const float &c)
The procedure of using these macros is followed.
In declaration of class of inherited Stub class, add [DECRMI_NameSpace_Method].
In method definition of inherited Stub class, use [DEFRMI_NameSpace_Method].
Here shows how you can use them.
// PIDL file contents global LobbyC2S 5000 { Foo([in] int a,[in] float b); } // Class that inherits Stub of LobbyC2S and operates RMI class LobbyC2SStub:public LobbyC2S::Stub { DECRMI_LobbyC2S_Foo; }; // Creation of RMI Foo routine DEFRMI_LobbyC2S_Foo(LobbyC2SStub) { // Parameter that gets passed to here is the same parameter of LobbyC2S.Foo of PIDL. a++; b++; return true; }
More detailed example on this is guided in 6.1 RMI stub 구현하기 of Part III. ProudNet Tutorial
Client and server inherit Proud.IRmiHost. Stub can be registered through the included method, Proud.IRmiHost.AttachStub.
Just like Proxy, you can attach more than two of Stub as long as their message ID doesn't overwrap with each other.
The operation method of attached Proxy and Stub
Proxy and stub attached to eigher Proud.CNetServer or Proud.CNetClient get registered to proxy list and stub list inside of Proud.CNetServer or Proud.CNetClient.
Proxy has a pointer of Proud.CNetServer or Proud.CNetClient that calls for sending method of Proud.CNetServer or Proud.CNetClient.
On the other hand, when Proud.CNetServer or Proud.CNetClient receives the message then it tosses it onto stub list. Each stub analyzes the header of received message and calls for appropriate RMI. (If there is no associated RMI, then it ignores it and passes an opportunity of analyzing to a next stub.)
When Proud.CNetServer or Proud.CNetClient is destructed, the link of proxy list and stub list contained inside get disconnected as well. When this happens, all stub linked to Proud.CNetServer or Proud.CNetClient in the past no longer calls for RMI and since every proxy also stops referring to Proud.CNetServer or Proud.CNetClient, RMI doesn't operate at all.
C++11에서의 Stub 붙이기
이 부절은 구 영어 도움말에서 번역이 안되어 있는 부절입니다. 추후 번역이 필요합니다.
C++11의 람다식을 이용하면 람다 캡처를 통해 클래스 상속 관계를 생략하는 등 더 간결한 프로그래밍이 가능합니다. 아래와 같이 Stub을 구현할 때 람다식을 사용하세요.
1. StubFunctional 인스턴스를 생성하세요.
2. StubFunctional에서 구현하고자 하는 RMI 함수를 람다식 형식으로 정의하세요. 필요시 PARAM_ 매크로를 사용하세요.
아래는 람다식으로 RMI stub을 구현하는 예입니다.
<exam.pidl> Func1([in] int a, [in] string b); <exam.cpp> class Exam { int x = 1; Exam::StubFunction examStub; void Main() { int y = 3; examStub.Func1_Function = [this, y]PARAM_Exam_Func1 { x+=a; y+=a; return true; }; } };
11.4Communication between hosts
In order to exchange messages between hosts in ProudNet, 4. Remote Method Invocation and 11. Usage of Remote Method Invocation must be predetermined. This section explains how you can send a message to another host with RMI.