프로그래밍 Part 3: 프로그램 실행 인자¶
iFun Engine 에서는 프로그램의 설정 내용은 MANIFEST.json
로 관리됩니다.
그러므로, 실행 인자를 전달하는 방법은 크게 MANIFEST.json 에 인자를 지정하는 방법과, 명령행 인자를 추가하는 방법이 있습니다.
방법1: MANIFEST.json 을 이용¶
MANIFEST.json 에 인자 추가하기¶
아래처럼 MANIFEST.json 에 arguments
라는 JSON property 를 추가하고 그 안에 사용할 인자들을 정의합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | {
"version": 1,
"components": [
{
"name": "MyProjectServer",
"arguments": {
"example_arg1": "val1",
"example_arg2": 100
},
"library": "libmy_project.so",
"dependency": {
...
"SessionService": {
"tcp_json_port": 8012,
...
},
...
}
}
]
}
|
서버 코드에서 인자 읽기¶
MANIFEST.json 에 추가된 인자들은 해당 서버의 Install 함수가 호출될 때 전달 됩니다. 아래는 위의 MANIFEST.json 을 읽는 경우입니다.
my_project_server.cc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class MyProjectServer : public Component {
public:
static bool Install(const ArgumentMap &arguments) {
LOG(INFO) << "Built using Engine version: " << FUNAPI_BUILD_IDENTIFIER;
// Kickstarts the Engine's ORM.
// Do not touch this, unless you fully understand what you are doing.
my_project::ObjectModelInit();
/*
* Parameters specified in the "arguments" section in your MANIFEST.json
* will be passed in the variable "arguments".
* So, you can give configuration data to your game server.
*
* Example:
*
* We have in MANIFEST.json "example_arg1" and "example_arg2" that
* have a string value and an integer value, respectively.
* So, you can access the arguments like below:
*/
string arg1 = arguments.FindStringArgument("example_arg1");
LOG(INFO) << "example_arg1: " << arg1;
int64_t arg2 = arguments.FindIntegerArgument("example_arg2");
LOG(INFO) << "example_arg2: " << arg2;
// You can override gflag like this: ./my_project-local --example_arg3=hahaha
LOG(INFO) << "example_arg3: " << FLAGS_example_arg3;
/*
* Registers various handlers.
* You may be interesed in this function and handlers in it.
* Please see "event_handlers.cc"
*/
my_project::RegisterEventHandlers();
return true;
}
}
|
server.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | namespace MyProject
{
public class Server
{
public static void Install(ArgumentMap arguments)
{
// Session open, close handlers.
NetworkHandlerRegistry.RegisterSessionHandler (
new NetworkHandlerRegistry.SessionOpenedHandler (OnSessionOpened),
new NetworkHandlerRegistry.SessionClosedHandler (OnSessionClosed));
// "echo" message handler for JSON type.
NetworkHandlerRegistry.RegisterMessageHandler ("echo", new NetworkHandlerRegistry.JsonMessageHandler (OnEcho));
// "echo_pbuf" message handler for Google Protocol Buffers.
NetworkHandlerRegistry.RegisterMessageHandler ("echo_pbuf", new NetworkHandlerRegistry.ProtobufMessageHandler (OnEchoPbuf));
// Parameters specified in the "arguments" section in your MANIFEST.json
// will be passed in the variable "arguments".
// So, you can give configuration data to your game server.
//
// Example:
//
// We have in MANIFEST.json "example_arg1" and "example_arg2" that
// have a string value and an integer value, respectively.
// So, you can access the arguments like below:
string arg1 = arguments.FindString ("example_arg1");
Log.Info ("example_arg1: {0}", arg1);
Int64 arg2 = arguments.FindInteger ("example_arg2");
Log.Info ("example_arg2: {0}", arg2);
// You can override gflag like this: ./mono-local --example_arg3=hahaha
Log.Info("example_arg3: {0}", Flags.GetString ("example_arg3"));
// Registers a timer.
//
// Below demonstrates a repeating timer. One-shot timer is also available.
// Please see the Timer class.
Timer.ExpireRepeatedly(WallClock.FromSec(1), OnTick);
}
}
}
|
방법2: Google Flag 로 추가¶
Google flag 추가하기¶
먼저 사용할 실행 인자를 Google Gflag 를 이용해서 코드 상에서 정의합니다.
이 때 사용되는 함수들은 다음과 같습니다.
DEFINE_bool |
boolean |
DEFINE_int32 |
32-bit integer |
DEFINE_int64 |
64-bit integer |
DEFINE_uint64 |
unsigned 64-bit integer |
DEFINE_double |
double |
DEFINE_string |
C++ string |
예를 들면 아래와 같습니다.
DEFINE_string(my_arg1, "기본값", "my_arg1에 대한 설명");
Note
C# 의 경우 mono/server.cs 가 아닌 src/{{project_name}}_server.cc 에 C++ 코드로 추가하셔야 됩니다.
서버 코드에서 flag 읽기¶
해당 flag 가 필요한 경우 DEFINE_XYZ() 와 매칭되는 DECLARE_XYZ() 라는 함수로 flag 를 선언 하고 코드 상에서 FLAGS_XYZ 라는 이름으로 사용하면 됩니다.
사용 가능한 DECLARE_XYZ() 함수들은 다음과 같습니다.
DECLARE_bool |
boolean |
DECLARE_int32 |
32-bit integer |
DECLARE_int64 |
64-bit integer |
DECLARE_uint64 |
unsigned 64-bit integer |
DECLARE_double |
double |
DECLARE_string |
C++ string |
my_project_server.cc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | // You can differentiate game server flavors.
DECLARE_string(example_arg3);
class MyProjectServer : public Component {
public:
static bool Install(const ArgumentMap &arguments) {
LOG(INFO) << "Built using Engine version: " << FUNAPI_BUILD_IDENTIFIER;
// Kickstarts the Engine's ORM.
// Do not touch this, unless you fully understand what you are doing.
my_project::ObjectModelInit();
/*
* Parameters specified in the "arguments" section in your MANIFEST.json
* will be passed in the variable "arguments".
* So, you can give configuration data to your game server.
*
* Example:
*
* We have in MANIFEST.json "example_arg1" and "example_arg2" that
* have a string value and an integer value, respectively.
* So, you can access the arguments like below:
*/
string arg1 = arguments.FindStringArgument("example_arg1");
LOG(INFO) << "example_arg1: " << arg1;
int64_t arg2 = arguments.FindIntegerArgument("example_arg2");
LOG(INFO) << "example_arg2: " << arg2;
// You can override gflag like this: ./my_project-local --example_arg3=hahaha
LOG(INFO) << "example_arg3: " << FLAGS_example_arg3;
/*
* Registers various handlers.
* You may be interesed in this function and handlers in it.
* Please see "event_handlers.cc"
*/
my_project::RegisterEventHandlers();
return true;
}
}
|
해당 flag 가 필요한 경우 Flags.GetString(“XYZ”) 형태로 값을 읽을 수 있습니다.
이 때 타입 별로 Get 할 수 있는 함수들은 다음과 같습니다.
GetBool |
boolean |
GetInt32 |
32-bit integer |
GetInt64 |
64-bit integer |
GetUInt64 |
unsigned 64-bit integer |
GetDouble |
double |
GetString |
C# string |
server.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | namespace MyProject
{
public class Server
{
public static void Install(ArgumentMap arguments)
{
// Session open, close handlers.
NetworkHandlerRegistry.RegisterSessionHandler (
new NetworkHandlerRegistry.SessionOpenedHandler (OnSessionOpened),
new NetworkHandlerRegistry.SessionClosedHandler (OnSessionClosed));
// "echo" message handler for JSON type.
NetworkHandlerRegistry.RegisterMessageHandler ("echo", new NetworkHandlerRegistry.JsonMessageHandler (OnEcho));
// "echo_pbuf" message handler for Google Protocol Buffers.
NetworkHandlerRegistry.RegisterMessageHandler ("echo_pbuf", new NetworkHandlerRegistry.ProtobufMessageHandler (OnEchoPbuf));
// Parameters specified in the "arguments" section in your MANIFEST.json
// will be passed in the variable "arguments".
// So, you can give configuration data to your game server.
//
// Example:
//
// We have in MANIFEST.json "example_arg1" and "example_arg2" that
// have a string value and an integer value, respectively.
// So, you can access the arguments like below:
string arg1 = arguments.FindString ("example_arg1");
Log.Info ("example_arg1: {0}", arg1);
Int64 arg2 = arguments.FindInteger ("example_arg2");
Log.Info ("example_arg2: {0}", arg2);
// You can override gflag like this: ./mono-local --example_arg3=hahaha
Log.Info("example_arg3: {0}", Flags.GetString ("example_arg3"));
// Registers a timer.
//
// Below demonstrates a repeating timer. One-shot timer is also available.
// Please see the Timer class.
Timer.ExpireRepeatedly(WallClock.FromSec(1), OnTick);
}
}
}
|
명령행 실행 시 인자 전달하기¶
이제 게임 서버는 --example_arg3
이라는 실행 인자를 인식하게 됩니다. 즉, --example_arg3=my_value
형태로 사용하게 됩니다.
$ ./my_game_server-local --example_arg3=my_value
혹은 EXTRA_ARGS 라는 환경 변수에 추가할 인자들을 모두 나열하셔도 됩니다.
$ EXTRA_ARGS="--my_arg1=my_value" ./my_game_server-local
또는
$ export EXTRA_ARGS="--my_arg1=my_value"
$ ./my_game_server-local
서비스로 실행시 인자 전달하기¶
게임 서버를 패키징해서 서비스로 실행하는 경우는 앞에서와 같이 실행 인자를 넘겨주는 것이 불가능합니다. 그 경우는 서비스 설정하기 에 언급된 파일들에 실행 인자를 정의해서 넘겨줄 수 있습니다.
Systemd:
etc/default/{{project-name}} 파일 열어서 아래와 같이 수정합니다.
# Set your environment variables here. EXTRA_ARGS="--example_arg3=my_value --example_arg4=another"
Upstart:
etc/upstart/default/{{project-name}} 파일에
export EXTRA_ARGS="--example_arg3=my_value --example_arg4=another"
형태로 입력합니다.Important
export
를 반드시 붙여야되며,EXTRA_ARGS
뒤에 나오는=
은 앞뒤로 공백없이 붙여써야 됩니다.