[C#][FX]DLLを利用した共有メモリの動作
こんにちわ。
外国為替取引のFXに利用するプログラムを作成しています。
その中で、
C#のプログラムAと
MQLという言語によるプログラムBにおいて、
共有メモリ読み書きを行うDLLを利用して、
(1)Aの結果を共有メモリに書き込み→Bで受け取って処理。
(2)Bの結果を共有メモリに書き込み→Aで受け取って処理。
という仕組みを作成しています。
(2)はできたのですが、(1)がうまくいきません。
知見をお持ちの方アドバイスいただけませんでしょうか。
以下詳細でございます。
●相談内容
共有メモリ書き込み時に以下エラーが発生し、書き込みができない。
「保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」
●ソース(一部抜粋。InitializeとRunは基盤システムからコールされます。)
【C#ソース】
using System.Runtime.InteropServices;
using System;
[DllImport("MemMap.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern string SetMemString(string tag, string msg);
public bool Initialize()
{
try{
Console.Write("try01");
SetMemString("TEST", "1");
Console.Write("try02");
SetMemMethod();
}catch(Exception e){
Console.Write(e.Message);
Console.Write(e.StackTrace);
}
return true;
}
public void SetMemMethod(){
SetMemString("TEST", "2");
}
public void Run(){
try{
Console.Write("try03");
SetMemString("TEST", "3");
}catch(Exception e){
Console.Write(e.Message);
Console.Write(e.StackTrace);
}
}
}
}
【コンソール】
try01
保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
場所 test.Main.SetMemString(String tag, String msg)
場所 test.Main.Initialize()
try03
保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
場所 test.Main.SetMemString(String tag, String msg)
場所 test.Main.Run(
【DLL】
MT4_EXPFUNC const char* __stdcall SetMemString(char *tag,char *msg)
{
/*static*/ string ret = "";
bool create = false;
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, tag);
if (!hMap) {
hMap= CreateFileMapping((HANDLE)0xFFFFFFFF , NULL ,
PAGE_READWRITE , 0 , 1024 , tag);
q.push(hMap);
create = true;
}
LPSTR strAllCmd =(LPSTR)MapViewOfFile(hMap , FILE_MAP_WRITE , 0 , 0 , 0);
lstrcpy(strAllCmd , msg);
FlushViewOfFile(strAllCmd,0);
UnmapViewOfFile(strAllCmd);
if(!create) CloseHandle(hMap);
return(ret.c_str());
}
●詳細
try01直後の初期化メソッド(Initialize)で直接コールするSetMemStringは問題なく出来ており、プログラムB側で読むことができていますが、
try02直後の初期化メソッド(Initialize)でコールするメソッドの中のSetMemStringと
try03直後のメイン処理(Run)の中のSetMemString
でエラーが発生します。
try02はソースの綺麗さを保つために別メソッドに切り出したいだけなので、
最悪初期化メソッドに直書きすればよいですが、
メイン処理なので、try03でエラーが発生するのはなんとしても解決したいです。
try01で呼べていることからDllImportのスコープがうまくできていないのでは?
と考えています。
継承元のExpertクラスはソースが隠蔽されていて、わかりませんが、
何かアドバイスいただけませんでしょうか。よろしくお願いします。
お礼
ありがとうございます。 MapViewOfFileについては、上記コードは不正終了しなかった一例として書いただけですので、実際には色々と実験していました。 …が、4KBの倍数にしてはいませんでした。 実際に4KBにしてそれを超えたところへ書き込もうとしてみると、見事に「不正終了」してくれました! また >範囲を超えたらアクセス例外が起きることに期待するのは間違い というのを確認できれば十分です。 一見必要そうな状況があった場合に、そのために変数を用意する必要が本当にあるかどうかが一番の気がかりだったわけですが 通常のメモリと同じように書き込み範囲のサイズを保存しておく方が万全ならば、その変数を「別の場所でも活用した」処理をさせることを考えられれば、パフォーマンス上も全然十分だと思います。 4についても、イメージ通りのようで、安心しました。 これで安心して先に進めそうです。