# Utilization of PIDL

## Using Custom Build Rules

> <mark style="color:orange;">Display Name</mark> : the name that will be displayed in Custom Build Rules. ex) PIDL Rule\ <mark style="color:orange;">File Name</mark> : create a rule filename. ex) PIDL\_Custom\_Build\_Rule\ <mark style="color:orange;">Directory</mark> : specify the location where the rule file will be saved. ex) C:\XXX\YYY

<figure><img src="/files/7l8imOJlfAtIIWKEQ0kp" alt=""><figcaption><p>Custom Build Rule setting</p></figcaption></figure>

The details of each setting are as follows:

```
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
```

After completing the settings, a **PIDL Build Rule** is added to **Custom Build Rules** as follows.

<figure><img src="/files/CKjFYMzqr81Rn0kiailm" alt=""><figcaption><p>Custom Build Rules</p></figcaption></figure>

Check out the newly created rules file, and when you create a file in your project, you will see that the Build Tool is automatically selected as PIDL.

## Using the Command Prompt (Command Prompt, cmd.exe)

If the **PIDL AddOn** or **Custom Build Rules** are not available, you can compile via command prompt on the Windows OS.

<figure><img src="/files/n3yrP4lhzREeEAhib0ok" alt=""><figcaption></figcaption></figure>

For **cs**, you can compile it with the **PIDL -cs** command.

<figure><img src="/files/0HHaYjVozdEmT0EYskG4" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}

* <mark style="color:orange;">PIDL.exe</mark> is located in the <mark style="color:orange;">util</mark> folder of the ProudNet installation path.
* Both Debug and Release must be set to the same.
* Do not follow the example with the path to <mark style="color:orange;">PIDL.exe</mark>, but set the path to PIDL in the path where ProudNet is installed.
  {% endhint %}

{% hint style="warning" %}

* In this example, we created a Common - PIDL folder and specified it as the PIDL compile path (outdir).
* Please do not follow that include path, but specify the required path for your project.
  {% endhint %}

<figure><img src="/files/OpS6J3Umep0N5iLdXi2j" alt=""><figcaption><p>Common - set outdir to PIDL, then set it to an additional include directory</p></figcaption></figure>

Check out the generated source files and include them in the Visual Studio project properties window to use them when you build.

## Using Customizations

{% hint style="info" %}
**Visual Stuido 2005, 2008 version**

* [**Custom Build Rules**](#custom-build-rules) can be used to create rule files
* One rule file with <mark style="color:orange;">.rules</mark> extension
  {% endhint %}

{% hint style="info" %}
**Visual Studio 2010 and later version**

* Can be used/cannot be created using [**Custom Build Rules**](#custom-build-rules)
* Three files are required: <mark style="color:orange;">.props</mark>, <mark style="color:orange;">.targets</mark>, and <mark style="color:orange;">.xml</mark>. Unable to use the <mark style="color:orange;">.rules</mark> file created from a previous version
  {% endhint %}

> **Two ways to use customizations**
>
> 1\. After creating a project in Visual Studio 2005 or 2008, create a <mark style="color:orange;">.rules</mark> file and set it to use, then convert the project to version 2010 or later.\
> : When converting a project, <mark style="color:orange;">.rules</mark> files are automatically converted to <mark style="color:orange;">.props</mark>, <mark style="color:orange;">.targets</mark>, and <mark style="color:orange;">.xml</mark>.<br>
>
> 2\. Create <mark style="color:orange;">.props</mark>, <mark style="color:orange;">.targets</mark>, and <mark style="color:orange;">.xml</mark> files and write your own XML code to use them

Visual Studio 2005, 2008 and Visual Studio 2010 and later versions have different defined macros.\
If the rule is not written in the macros used in the Visual Studio 2010 and later versions, you must convert to the macros used in the Visual Studio 2010 and later versions or modify <mark style="color:orange;">.props</mark>, <mark style="color:orange;">.targets</mark>, and <mark style="color:orange;">.xml</mark> respectively after the conversion.

## Using include or import in PIDL content

As you develop your programs, you may want to **include** or **import** statements in your <mark style="color:orange;">.pidl</mark> file.

```
#include "a/b/c.h"
 
class MyStub // PIDL compilation output
{
    ...
}
```

To do this, use the following inside your PIDL content.

{% tabs %}
{% tab title="C++" %}

```cpp
#include "a/b/c.h" 
// for C++ language. semicolon is mandatory!
```

{% endtab %}

{% tab title="Java" %}

```java
import com.mycompany.mygame; // for Java
```

{% endtab %}
{% endtabs %}

## Marshaling

{% tabs %}
{% tab title="C++" %}

#### Using custom class types for RMI

```cpp
// MyType.h
 
namespace Proud
{
    // The contents of the called RMI function are converted into a string and output.
    // Useful for creating logs.
    void AppendTextOut(String &a,const MyType &b);
 
    // Reads the contents of a custom type from the message buffer.
    CMessage& operator>>(CMessage &a, MyType &b);
 
    // Put the contents of the custom type into the message buffer.
    CMessage& operator<<(CMessage &a, const MyType &b);
}
 
```

Inside ProudNet's RMI functionality, we are using <mark style="color:orange;">Proud.CMessage</mark>. And RMI parameters are marshaled through overloading of the above functions. <mark style="color:orange;">Proud.CMessage</mark> is being used here.\ <mark style="color:orange;">Proud.CMessage</mark> holds the message data used by ProudNet to turn RMIs into messages or read parameters from messages, and is used as a stream object.<br>

An example of implementing a stream in a marshaling function is as follows.

```cpp
namespace Proud
{
    CMessage& operator>>(CMessage &a, MyType &b)
    {
        a>>b.x,b.y>>b.z>>b.w;
        return a;
    }
    CMessage& operator<<(CMessage &a, const MyType &b)
    {
        // Do not use a.UseInternalBuffer()!
        a<<b.x,b.y<<b.z<<b.w;
        return a;
    }
    void AppendTextOut(String &a,const MyType &b)
    {
        String f;
        f.Format(L"{x=%f,y=%f,z=%f,w=%f}",b.x,b.y,b.z,b.w);
        a+=f;
    }
}
```

Finally, before including the proxy and stub files created by the PIDL compiler, the header file where the above overloaded methods are declared must be included first.

```cpp
// Example1
#include "MyType.h"
#include "MyPIDL_proxy.h"
 
// Example2
#include "MyType.h"
#include "MyPIDL_stub.h"
```

\
See  <mark style="color:orange;">\<installed folder>/sample/CustomTypeMarshal</mark> or <mark style="color:orange;">\<Sample/CasualGame/GCServer/FarmCommon.h></mark> for examples of actual implementations. To verify that your own marshalling functionality works, use <mark style="color:orange;">Proud.TestMarshal()</mark>.
{% endtab %}

{% tab title="C#" %}
After serialising and sending the <mark style="color:orange;">CFastArray</mark> on the C++ side, the C# side receives it, deserializes it, and uses it to proceed to step 5.\
In this example, the C# client calls an RMI called Ping, and the C++ server that receives it calls the StudentList RMI, passing a <mark style="color:orange;">CFastArray</mark> in C++ to the C# side, which receives it as a List.

1. [Writing a C# Student class](#1-c-student)
2. [Writing a C++ CStudent class](#2-c++-cstudent)
3. [Writing a PIDL](#3-pidl)
4. [Writing C++ marshaling code](#4-c++)
5. [Writing C# marshaling code](#5-c)

#### (1) Writing a C# Student class

```csharp
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);
        }
    }
} 
```

#### (2) Writing a C++ CStudent class

```cpp
class CStudent
{
    public:
    Proud::String Name;
    int ID;
    int Kor;
    int Eng;
    int Mat;
}; 
```

#### (3) Writing a PIDL

#### S2C.PIDL

<pre data-line-numbers><code><strong>rename cs(Proud::CFastArray&#x3C;CStudent>, System.Collections.Generic.List&#x3C;CsClient.Student>);
</strong><strong>[marshaler(cs)=CsClient.MyMarshaler]
</strong>global S2C 3000
{
<strong>    StudentList([in] Proud::CFastArray&#x3C;CStudent> students);
</strong>} 
</code></pre>

{% hint style="success" %} <mark style="color:orange;">Line1</mark>: The rename keyword is used for PIDL communication between different languages. The name must include the Namespace.

<mark style="color:orange;">Line2</mark>: Specify the marshaler to be used on the C::side with the marshaler(cs) keyword. The name must include the Namespace.

<mark style="color:orange;">Line5</mark>: Create a StudentList PIDL. Basically, just write it as you would on the C++ side.
{% endhint %}

**C2S.PIDL**

```
[marshaler(cs)=CsClient.MyMarshaler]
global C2S 4000
{
    Ping([in] int value);
} 
```

This example PIDL code sends a StudentList when a client pings it, and you can build it to create a  <mark style="color:orange;">.h</mark>, <mark style="color:orange;">.cpp</mark> and <mark style="color:orange;">.cs</mark> file.

&#x20;

#### (4) Writing C++ marshaling code

Code for marshaling a CStudent class created as an example.&#x20;

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

This is the code that sends the StudentList when a ping is sent from the C# client.

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

&#x20;

#### (5) Writing C# marshaling code

Marshalling in C# is developed by inheriting, implementing, and replacing <mark style="color:orange;">Nettention.Proud.Marshaler</mark> and works with the keyword <mark style="color:orange;">marshaler(cs)=CsClient.MyMarshaler</mark> declared in the PIDL without having to do it yourself.

```csharp
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);
            }
        }
    }
} 
```

```csharp
g_S2CStub.StudentList = (remote, rmiContext, students) =>
{
    lock(g_lock)
    {
        // You can do this by using students passed into List<Student>.
        foreach (var s in students)
        {
            Console.WriteLine(s.ToString());
        }
    }
    return true;
};
```

{% endtab %}
{% endtabs %}

### - Marshaling methods based on conditions

There are ways to marshal information about a character in an RMI parameter where each field is valid or invalid for different types of characters. You can implement different marshalling using switch/case statements or polymorphism of objects.\
\
Below is an example of using swich/case.

<details>

<summary> <span data-gb-custom-inline data-tag="emoji" data-code="27a1">➡️</span> example of using swich/case</summary>

```cpp
namespace Proud
{
    enum UnitType
    {
        Zergling,     // StarCraft's juggling (ground type normal attack unit)
        Queen,        // Queen of Starcraft (Flying Special Technology Use Unit)
        Broodling    // A short-lived attack unit created by Queen using her brudling skills
    };
 
    struct Unit
    {
        UnitType m_type;          // Unit's type
        Vector2D m_position;    // Unit;s location
        int m_energy;            // Unit's energy (or mana) reserves -> Queen only
        float m_lifeTime;        // Unit's survival time limit -> Bridling only
        int m_attackPower;        // Unit's attack power->Juggling only
    };
 
    CMessage& operator<<(CMessage& msg,const Unit& unit)
    {
        msg<<unit.m_type<<unit.m_position;
        switch(unit.m_type)
        {
        case Zergling:
            msg<<unit.m_attackPower;
            break;
        case Queen:
            msg<<unit.m_energy;
            break;
        case Broodling:
            msg<<unit.m_lifeTime;
            break;
        }
        return msg;
    }
 
    CMessage& operator>>(CMessage& msg,Unit& unit)
    {
        msg>>unit.m_type>>unit.m_position;
        switch(unit.m_type)
        {
        case Zergling:
            msg>>unit.m_attackPower;
            break;
        case Queen:
            msg>>unit.m_energy;
            break;
        case Broodling:
            msg>>unit.m_lifeTime;
            break;
        }
        return msg;
    }
}
```

</details>

### - Marshaling data in Bit

You can marshal data in bits to reduce the amount of data stored in the message. \ <mark style="color:orange;">Proud.CMessage</mark> has the following methods of storing data in bit units.

<table><thead><tr><th width="351">Method</th><th>Description</th></tr></thead><tbody><tr><td>Proud.CMessage.ReadBits</td><td>Read in bit</td></tr><tr><td>Proud.CMessage.WriteBits</td><td>Write in bit</td></tr></tbody></table>

<details>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="27a1">➡️</span> Example</summary>

```cpp
namespace Proud
{
    struct MyType
    {
        int x,y,z;
    };
    CMessage& operator>>(CMessage &a, MyType &b)
    {
        // Use 6 bits to read the x value
        a.ReadBits(b.x,6);
        // Use 3 bits to read the y value
        a.ReadBits(b.y,3);
        // Use 15 bits to read the z value, i.e. sum 6+3+15=24 bits (3 bytes)
        a.ReadBits(b.z,15);
        return a;
    }
    CMessage& operator<<(CMessage &a, const MyType &b)
    {
        a.WriteBits(b.x,6); // Store x,y,z values in bits.
        a.WriteBits(b.y,3);
        a.WriteBits(b.z,15);
        return a;
    }
}
```

</details>

{% hint style="warning" %}
**Precautions of marshaling data in bits**&#x20;

The number of bits you want to record should not be outside the range of the actual value you want to record.\
For example, if you want to write an int and the value inside is actually negative, the first bit is 1. In this case, if you try to write 31 bits or less to reduce the amount of bits, the value of the first bit will be missing, so be aware of this when doing reading/writing in bits.
{% endhint %}

### - Marshaling enum types

To marshal an enum type, implement a function like the one below.

```cpp
enum type { ... } ;
 
namespace Proud
{
    inline CMessage& operator<<(CMessage& a,type b)
    {
        a<<(int)b;
        return a;
    }
    inline CMessage& operator>>(CMessage& a,type& b)
    {
        int x;
        a>>x;
        b=(type)x;
        return a;
    }
    inline void AppendTextOut(String &a,type b)
    {
        String txt;
        txt.Format(L"%d",(int)b);
        a+=txt;
    }
}
```

By using the macro <mark style="color:orange;">PROUDNET\_SERIALIZE\_ENUM</mark> already defined in ProudNet, the above implementation can be easily accomplished as follows.

```
PROUDNET_SERIALIZE_ENUM(type)
```

### - Marshaling collections (arrays, etc.)

ProudNet provides you with the ability to marshal a few basic types of collections (e.g., arrays). It supports <mark style="color:orange;">Proud.CFastArray</mark>, <mark style="color:orange;">Proud.CFastMap</mark>, <mark style="color:orange;">std.vector</mark> and <mark style="color:orange;">CAtlArray</mark>.&#x20;

{% hint style="info" %}
&#x20;See the operator>>, operator<< override in <mark style="color:orange;">marshaler.h</mark> for more details.
{% endhint %}

```
// Below is an example of declaring an array type in PIDL.
Foo([in] Proud::CFastArray<MyType> a, [in] std::vector<MyType> b);
```

If you need marshaling of collection types other than those defined by default in <mark style="color:orange;">marshaler.h</mark>, you will need to implement an override corresponding to the collection you need. For this, see [**Using custom class types for RMI**](#using-custom-class-types-for-rmi) or <mark style="color:orange;">marshaler.h</mark> for examples already implemented.

\
If you want to marshal for a collection type that ProudNet does not yet support, use the following routine as a guide to write it.

<details>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="27a1">➡️</span> example of marshaling <mark style="color:orange;">std.vector</mark></summary>

```cpp
namespace Proud
{
    // Serialisation functions available in vector
    // for output to stream
    template<typename elem>
    inline CMessage& operator>>(CMessage &a, std::vector<elem> &b)
    {
        // Get the size.
        int size;
        a >> size;
 
        // Raise an exception if the size is unacceptable.
        // You may suspect that it has been hacked.
        if (size<0 ||size >= CNetConfig::MessageMaxLength)
            ThrowExceptionOnReadArray(size);
 
        // To reduce memory fragments
        b.reserve(size);
        b.resize(0);
 
        // Reads the array items one by one.
        elem e;
        for (int i = 0;i < size;i++)
        {
            a >> e;
            b.push_back(e);
        }
        return a;
    }
 
    // Serialisation functions available 
    // for unary item elem such as vector, list, etc.
    // for input from stream
    template<typename elem>
    inline CMessage& operator<<(CMessage &a, const std::vector<elem> &b)
    {
        // Record the size of the array.
        int size = (int)b.size();
        a << size;
        
        // Record each array argument.
        for (std::vector<elem>::const_iterator i = b.begin();i != b.end();i++)
        {
            a << (*i);
        }
        return a;
    }
 
    template<typename elem>
    inline void AppendTextOut(String &a, std::vector<elem> &b)
    {
        a += L"<vector>";
    }
}
```

</details>

## List of keywords

<table data-full-width="false"><thead><tr><th width="128.33333333333331">Name of keyword</th><th width="304">Description</th><th>Example usage</th></tr></thead><tbody><tr><td>access</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Setting access to proxy and stub classes in a namespace</td><td>[access=Permission name]</td></tr><tr><td>byval</td><td>Passing parameters as value</td><td>P2PChat([in] Proud::String a, [in, byval] int b);</td></tr><tr><td>global</td><td>Namespace access (currently global only)</td><td>global Simple 2000 { ... }</td></tr><tr><td>in</td><td>Enter parameters</td><td>Chat([in] string txt);</td></tr><tr><td>include</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Insert include into the result</td><td>#include "a/b/c.cpp"</td></tr><tr><td>marshaler</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Marshaller for custom types</td><td>[marshaler(cs) = SimpleCSharp.CMyMarshaler]</td></tr><tr><td>mutable</td><td>Passing a parameter as mutable (:=reference)</td><td>Chat([in, mutable] string txt);</td></tr><tr><td>private</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Setting access to proxy and stub classes in a namespace</td><td>[access=private]</td></tr><tr><td>protected</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Setting access to proxy and stub classes in a namespace</td><td>[access=protected]</td></tr><tr><td>public</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Setting access to proxy and stub classes in a namespace</td><td>[access=public]</td></tr><tr><td>rename</td><td>Compiling with substitutions in a specific environment</td><td>rename cs(Proud::String, System.String);</td></tr><tr><td>using</td><td><mark style="color:orange;">[<strong>C#</strong>]</mark> Insert the using keyword in the result</td><td>using(cs) System.XXX;</td></tr></tbody></table>

## \[C#] To pass a variety of parameters

```
global Namespace name 2000 
{
    Function name([in] int Variable name);
}
```

When PIDL is written as above, the PIDL compiler compiles it as follows for the base type.

<pre><code>namespace Namespace name
{
    class Proxy : public ::Proud::IRmiProxy
    {
    public:
<strong>        virtual bool Function name( ::Proud::HostID remote, ::Proud::RmiContext&#x26; rmiContext , const int&#x26; Variable name) PN_SEALED; 
</strong>        ...
    }
}
</code></pre>

If you want to change the delivery method, use the keywords below.

<table><thead><tr><th width="184.33333333333331">Name of keyword</th><th width="259">Example (PIDL)</th><th>Example (output)</th></tr></thead><tbody><tr><td>None</td><td>Chat([in] int val);</td><td>...Chat(..., const int&#x26; val)...</td></tr><tr><td>byval</td><td>Chat([in, byval] int val);</td><td>...Chat(..., const int val)...</td></tr><tr><td>mutable</td><td>Chat([in, mutable] int val);</td><td>...Chat(..., int&#x26; val)...</td></tr></tbody></table>

***

## :arrow\_left: [Back](/proudnet.eng/proudnet/using_pn/pidl.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.proudnet.com/proudnet.eng/proudnet/using_pn/pidl/using_pidl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
