DelphiとVCの各プロセスで、メモリ共有のためMapViewOfFileを使用して、開始アドレスを取得します。
○Delphi側
レコード型のポインタを使用して、配列で管理
TFile = Record
m_arr array[0..100] of integer;
end;
tf :^TFile;
tf := MapViewOfFile( )
tf.m_arr[1] := 7
○VC側
ポインタで管理
LPVOID cMap;
int *cm;
cMap = ::MapViewOfFile( )
cm = (int *)cMap;
*(cm +1) = 7
このとき、例えば*(cm+10) = 5 とVCでした場合、
Delphi側で期待しているのはtf.m_arr[10] = 5の値ですが、
tf.m_arr[8] が 5になります。
このずれがなぜ生じてしまうのかわかりません。
考えられることありますか?
また開始アドレス自体が同じかどうか調べる方法ありませんか?
よろしくお願いします。
packed record かな?
http://srgia.com/docs/dbl/DelphiBugList0623.html
ありがとうございます。
そーゆうこともあるんだと知れました。
ですが今回のケースは違うようです。
packed を追記しましたが、結果は変わりませんでした。
こんにちは.Mr.XRAYです.
>また開始アドレス自体が同じかどうか調べる方法ありませんか?
VC側で作成した共有メモリのと,Delphi側のそれと,という意味でしたら,
違いますよ.きっと.多分.
Delphi側というより,Aというアプリで,共有メモリを作成したとします.
でも,他のアプリでは,Aというアプリが共有メモリを作成したぞ!
ということを知ることはできないのではないかと思われますから.
もしからしたら,同じアドレスに割り当てることができるかも知れませんが,
ちょっと分かりません.
もっとも,同じだったら困ることになると思うのですが.
これ以上は,何とも.
ちょっと前に,レコード型のメンバーの数を知りたい,という質問がありましたが,
実際にはそうではなかった,という痛い目に会いましたので.
あれま,ゴメンなさい.読み返したら,違うんですね.
共有メモリに,他のアプリからアクセスする話なんですね.失礼しました.
実際に確認可能なコードがないので,確実なことは言えませんが,
VCの型とサイズ,Delphi側の型とサイズの問題かも知れません.
MapViewOfFile が 返す値が アドレス
ありがとうございます。
訂正があります。
> Delphi側で期待しているのはtf.m_arr[10] = 5の値ですが、
> tf.m_arr[8] が 5になります。
と書きましたが、VC、DelphiともにIntの場合は
tf.m_arr[9] が 5になります。
KHE00221さんの言うとおり、
MapViewOfFileの返す値が開始アドレスだと認識しているので、
どの型であろうと
*cm と tf.m_arr[0] は等しい値になりませんか?
int型だとわかりにくいのでchar型で実験してみては
また逆のパターン(Delphiで書きこみしてVCで読み込み)も
検証してみたら原因がつかめるのでは?
メモリ関係についてはVC側の方がデバッグしやすいかも。
#当方VCのコードは書けるのですがDelphiのスキルが足りないので
#検証できません。再現できるソースを載せてはどうでしょう。
Charでも試しました。
Char(VC) - ShortInt(Delphi) で行うと
例えば
VCでcm+5 = 5 → Delphiでtf.m_arr[1] = 5となり。
Delphiでtf.m_arr[8]=8 → VCでcm+12 = 8 となります。
4要素分ずれますね。
うーんShortでやると2要素分ずれるので、
結果4バイトずれてることになりますね。
下記コードで実験してみましたけど特にずれは無かったですね。
Delphi側
PData = ^TData;
TData = record
Data: Array[0..10] of Byte;
end;
const
SFILEMAP_TEST = 'FILEMAP_TEST';
procedure TForm1.FormDestroy(Sender: TObject);
begin
if FHMap <> 0 then
begin
CloseHandle(FHMap);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FHMap := CreateFileMapping(INVALID_HANDLE_VALUE, Nil, PAGE_READWRITE, 0, 1024, SFILEMAP_TEST);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
p: PData;
begin
if FHMap <> 0 then
begin
p := MapViewOfFile(FHMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
ShowMessage(IntToStr(p.Data[1]));
UnmapViewOfFile(p);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
p: PData;
begin
if FHMap <> 0 then
begin
p := MapViewOfFile(FHMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
p.Data[1] := 5;
UnmapViewOfFile(p);
end;
end;
VC側ダイアログアプリ
コンストラクタで
m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 1024, _T("FILEMAP_TEST"));
デストラクタで
if (m_hMap)
CloseHandle(m_hMap);
void CMapFileDlg::OnBnClickedButton1()
{
LPVOID pMap;
if (m_hMap)
{
pMap = MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
char* pC = PCHAR(pMap);
UnmapViewOfFile(pMap);
}
}
void CMapFileDlg::OnBnClickedButton2()
{
LPVOID pMap;
if (m_hMap)
{
pMap = MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
char* pC = PCHAR(pMap);
pC[2] = 10;
UnmapViewOfFile(pMap);
}
}
> どの型であろうと
> *cm と tf.m_arr[0] は等しい値になりませんか?
レコードの先頭=配列の先頭要素のアドレスとは限りません。
本物のソースではm_arrが動的配列だということはないですか?
tf :^TFile;
と
m_arr[0] のアドレスを比べてごらん?
みなさん回答ありがとうございます。
色々試していましたが、
結果Record型に消したはずの4バイトの型宣言がm_arr の前にありました。
それは4バイトずれますね…。
ポカですいません。
ただメモリに関して色々ためしたので、非常に勉強になりました。
また何かありましたらよろしくお願いします。
ツイート | ![]() |