2016-04-19 8 views
1

私は、Delphiで書かれたEXEから情報を受け取ろうとしています。 EXEは、私にそのデータ構造の一つへのポインタを渡します。Visual StudioのDelphi WideString MFC

Type 
    RecordType = Record 
    St: WideString; 
    Next: Pointer; 
    End; 

Var 
    DataRec: ^RecordType; 

だから、Visual StudioのMFCに私は類似しているはずのデータ型を宣言した:

struct RecordRec 
{ 
    BSTR St; 
    void *Next; 
}; 

RecordRec *DataRec; 

デルファイヘルプWideStringのことを言いますただし、BSTRと互換性がありますが、これは機能しません。私は、デバッグモードで自分の聖を見てみると、それは

"0x0000000000000000 <Bad Ptr> wchar_t *" 

を言う私は、Visual StudioのMFCでWideStringに相当を宣言するのか分かりません。

それは私が宣言しShortStringはだった場合:

struct RecordRec 
{ 
    BYTE StLen; 
    char St[255]; 
    void *Next; 
}; 

が、これはWideStringに動作しないと私は本当に私は〜2^30(1,073,741,824)文字での変数を宣言するべきだと思いませんそれ。

私には何が欠けていますか?私は本当に誰かが助けることを願っています。

+3

ポインタ....そのアドレス空間において?どのような方法でポインタを送信するのですか? – MBo

+1

非常に複雑です。最初に、Windowsサービスがあります。 Windowsが起動すると、サービスが自動的に起動して実行されます。 Delphi EXEが実行されると、サービスの一部であるDLL内の関数が呼び出され、サービスにそのデータへのポインタが渡されます。 Visual StudioのMFCプログラムは、サービスの関数を呼び出してポインタのコピーを取得します。しかし、それは私が悪いPtrを参照している私のMFCプログラムになるとき。これは、ShortStringが使用されたときに動作するために使用されていましたが、物事がWideStringに更新され、MFCの同等の宣言がどのようなものか分かりません。 – Gary

+1

質問本体にすべての詳細を追加します。彼らは非常に重要です。 DLLとの間でWideString型を渡すことは正しいアプローチですが、すべての状況を記述する – MBo

答えて

1

Delphi WideStringは確かにBSTRのラッパーであるが、あるプロセスから別のプロセスにそのまま渡すことができるわけではありません。そのデータはであり、プロセス境界を通過するときはとなります。 COMは自動的にそれを自動的に処理しますが、生のポインタBSTRを手動で渡すことはありません。

したがって、文字データのIPCセーフデータブロック(ShortString回避策に似ています)を提供するようにDelphiアプリケーションを変更できない場合、受信側アプリケーションはBSTRデータを手動でマーシャリングする必要があります。これは、そのためReadProcessMemory()を使用することができます。

  • は '(BSTRデルファイアプリのアドレス空間内からの長さの文字データがwchar_t要素でその長さを指定する4バイトの整数が付いている)
  • BSTRを読みます
  • wchar_t[]指定された長さの配列を独自のアドレス空間に割り当てます。
  • Delphiアプリケーションのアドレス空間の文字データを、独自のアドレス空間の配列に読み込みます。例えば

(エラーを簡潔にするために省略取り扱い):

RecordRec *DataRec = ...; 
std::wstring DataSt; 

if (DataRec->St) 
{ 
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, TheDelphiAppProcessID); 
    int len = 0; 
    SIZE_T numRead = 0; 
    ReadProcessMemory(hProcess, LPBYTE(DataRec->St)-4, &len, 4, &numRead); 
    if (len > 0) 
    { 
     DataSt.resize(len); 
     ReadProcessMemory(hProcess, DataRec->St, &DataSt[0], len*2, &numRead); 
    } 
    CloseHandle(hProcess); 
} 

// use DataSt as needed... 
+1

@RudyVelthuisを表示しています。あなたはそのドキュメントを誤解しています。 'BSTR'は、集中システムメモリマネージャ(WideStringがUnicodeStringよりも効率的でない理由の1つです)を使用してCOM関数によって*割り当てられますが、データ自体はアプリケーションのアドレス空間の割り当てにあり、それが割り当てる他のもののように。あなたは、 'wchar_t * 'を入力として受け付けるアプリケーションの関数に' BSTR'を渡すことができ、関数は文字データに直接アクセスできます。問題のDelphiアプリはDLL関数を呼び出しており、その関数はデータを別のサービスプロセスに渡しています。 –

+1

'var b:BSTR; b:= SysAllocString( 'Test'); MessageBoxW(0、PWideChar(b)、 ''、MB_OK); SysFreeString(b); '' BSTR'を割り当てることを要求するappプロセスのアドレス空間で 'BSTR'データが利用できなかった場合、そのコードは実行できません。 Delphiの文字列がBorlandMMとFastMMとScaleMMとの間で割り当てられているかどうかは関係ありませんが、COMがメモリマネージャであれば問題ありません。割り当てられたデータは呼び出し元のアプリケーションのメモリアドレス空間に存在するため、アクセス可能で、メモリマネージャによって*追跡される*ため、後で正しく解放されます。 –

+1

システム層でCOM自体の中に 'BSTR'が存在する場合、マーシャルはプロセス境界を越えて' BSTR'を渡す必要はなく、 'BSTR'ポインタはそのまま渡すことができます(' HWND'のように)。しかし、そうではありません。なぜなら、 'BSTR'ポインタは大域スコープを持たず、大部分のメモリ割り当てのようにプロセススコープを持っているからです。従って、一つのアドレス空間から別のアドレス空間へのプロセス境界を横断して 'BSTR'データをマーシャリングする必要があります。 –

2

あなたは何も欠けていません。 DelphiのWideStringは実際にはBSTRに相当します。デバッガに表示される値は、NULLポインタです。 Delphiはこれを空の文字列として扱います。あなたはおそらくそれを同じように扱うべきです。

+1

しかし、Delphi側では空ではありません。私はそれをテストして、私がMFC側で見ると期待している値を埋めました。 – Gary

+2

あなたの問題は他の場所にあります。あなたが質問で提供したものに何も問題はありません。 –

1

デルファイ1(DP)とVS 1(VSP)の2つのプロセスがあります。それぞれには独自のアドレス空間があり、DP内の有効なポインタはVSPでは無効です。そのため、<Bad Ptr>(例外?)が表示されます。

ところで、私はVSPのアドレスが64ビットであることに気付きました。 Delphiは64ビット処理もしていますか?

共有メモリを介して何らかのプロセス間通信(IPC)が必要です。

サービスとMFCプログラムを制御できるため、受け取ったデータをDLLの名前付きメモリマップファイルに保存してから、MFCプロセスが開いてデータを読み込むことができます。

+1

@Rudy Velthuis私は見るが、著者は「EXEはデータ構造の1つに**ポインタ**を渡し、 '^ RecordType'type – MBo

関連する問題