私はたくさん見回しましたが、私がやっていることと似たような解決策を見つけることができないようです. ネイティブ C++ アプリとマネージ C# アプリの 2 つのアプリケーションがあります。C++ アプリは、メモリ マネージャーで使用されるバイトのプールを割り当てます。このメモリ マネージャーに割り当てられた各オブジェクトにはヘッダーがあり、各ヘッダーには、オブジェクトに付けられた名前を指す char* があります。C# アプリは、このメモリのビューアーとして機能します。メモリ マップ ファイルを使用して、C++ アプリの実行中に C# アプリがメモリを読み取れるようにします。私の問題は、ヘッダー構造からオブジェクトの名前を読み取ってC#で表示しようとしている(または単に文字列に保存しようとしている)ことです。アンセーフ コードを使用して、 を構成する 4 バイトをに変換char*
しIntPtr
、それを に変換してvoid*
、 を呼び出すことができますMarshal.PtrToStringAnsi
。これはコードです:
IntPtr namePtr = new IntrPtr(BitConverter.ToInt32(bytes, index));
unsafe
{
void* ptr = namePtr.ToPointer();
char* cptr = (char*)ptr;
output = Marshal.PtrToStringAnsi((IntPtr)ptr);
}
この場合、bytes
は、ネイティブ アプリによって作成されたすべてのバイト プールを表すメモリ マップ ファイルから読み取られた配列でindex
あり、名前ポインターの最初のバイトのインデックスです。
マネージ側では、 への呼び出しによって返されるnamePtr.ToPointer()
アドレスが、ネイティブ アプリの名前ポインターのアドレスとまったく同じであることを確認しました。これがネイティブ コードの場合は、単にptr
a にキャストするだけchar*
で問題ありませんが、私が読んだマネージ コードでは、マーシャラーを使用してこれを行う必要があります。
このコードはさまざまな結果をもたらします。cptr
null の場合もあれば、 を指している場合もあれば\0
、いくつかのアジア文字を指している場合もあります (PtrToStringAnsi
メソッドを実行すると、一見無関係な文字が生成されます)。何かと思ったのですが、固定ポインタfixed
が生成されます。そして、デバッガーToPointer
へのキャストの後に、またはそのようなことを言うことがあります(戻ってくるさまざまなものをすべて再現するのは簡単ではありません)。また、メモリを読み取るときにアクセス違反が発生し、C++ 側につながることもあります。char*
Unable to evaluate the expression. The pointer is not valid
C++ 側では、ポインタを格納するメモリはメモリ マップド ファイルの一部ですが、テキストを構成する実際のバイトはそうではないため、メモリを実際に読み取る際に問題が発生する可能性があると考えました。そこで、メモリへの読み取り/書き込みアクセスを変更する方法を調べたところ (Windows では注意してください)、Windows ライブラリで VirtualProtect メソッドを見つけました。これは、メモリへのアクセスを PAGE_EXECUTE_WRITECOPY に変更するために使用します。そのアドレスへのポインタがあれば、そこにあるものを少なくとも読み取ることができます。しかし、それでも問題は解決しませんでした。
手短に言えば:
char 配列 (C++ アプリで割り当てられた) の最初の char へのポインター (C#) があり、その char の配列を C# の文字列に読み取ろうとしています。
編集:
ソース ヘッダーは次のようになります。
struct AllocatorHeader
{
// These bytes are reserved, and their purposes may change.
char _reserved[4];
// A pointer to a destructor mapping that is associated with this object.
DestructorMappingBase* _destructor;
// The size of the object this header is for.
unsigned int _size;
char* _name;
};
_name
フィールドは、C# で逆参照しようとしているフィールドです。
編集:
現在のところ、以下に示すソリューションを使用しても、マネージ コードでこの char* を逆参照できません。そのため、メモリ マップト ファイルによって参照されるプールに char* のコピーを作成し、それへのポインターを使用するだけです。これは機能するため、これは保護関連の問題であると私は信じています。ある時点でこれを回避する方法を見つけたら、自分の質問に答えます。それまでは、これが私の回避策になります。助けてくれたすべての人に感謝します!