参照渡しとライブラリにまつわるバグ?

公式フォーラムで、参照渡しとライブラリにまつわるバグ?について投稿があったので紹介しておきます。
参照渡しを知らない人は、「参照渡しは、とても便利かも!」を読んで頂くとして、以下に簡単な再現コードを書きました。




まずは、ライブラリを使わない場合のコード

void foo1(int &ret) // & を付けて、retを参照渡し宣言
{
  ret = 123; // retへの値の代入は、実際は、num に値を代入することになる。
}
/////////////////////////////////////////////////
int start()
{ 
  int num = 0;
  foo1(num); 
  Alert(num); // num=123 が表示される。
}

特に問題のない、ごく普通な参照渡しのサンプルコードです。


関数 foo1 を 外部ファイル test.mq4 ( test.ex4 ) としてライブラリ化してみると…

// \experts\libraries\test.mq4
#property library    // ライブラリ化時に忘れてはいけない一行
void foo1(int &ret)
{
  ret=123;
}


呼び出し側は、以下の通り。

#import "test.ex4"
void foo1(int &ret);
#import
/////////////////////////////////////////////////
int start()
{ 
  int num = 0;
  foo1(num);  // 参照渡しで123が代入されることを期待するも…
  Alert(num); // num=0 が表示される。(ノ_<。)
}

ライブラリ化の手順には、一見なんの誤りも無いように見えますが、結果として意図した動作をしなくなります。
そこで、オンラインヘルプを確認すると、

If there is a need to pass data of the int or double type, then the one-dimensional array of the corresponding type should be passed by reference as a parameter.

と書かれているので、上記の場合、MT4 のバグではなく仕様ということで、配列の参照渡しに書き換える必要があるのでした。参照渡しを多用したコードをライブラリ化する時は要注意ですね。
(個人的には、あまりex4のライブラリ化はしないで、#include だけで済ませるほうが良いと思います...)


いやぁ、プログラムって本っ当に難しいもんですね〜 by Mike Mizno