5

C# プロジェクトでは、構造体に参照を配置してオブジェクト パラメーターを渡す必要があります。つまり、ディスパッチャーに渡された構造があります

struct SOMESTRUCT
{
    public int lpObject;
}

lpObject は、次のようなカスタム オブジェクトへのポインターを保持します。

class SomeClass
{
    private string foo;
}

そして、SOMESTRUCT 構造体がメソッドからメソッドへと渡され、最終的にコードに到達します。実行フローも奇妙な SOMSTRUCT システムも変更できないため、唯一の解決策は、オブジェクトを次のようなポインターにキャストすることだと推測しました。

var myObject = new SomeClass();
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned);
int myRef = GC.AddrOfPinnedObject().ToInt32();
GC.Free();

SOMESTRUCT struct;
struct.lpObject = myRef;
someMethod(struct);

ただし、lpObject フィールドから myObject メンバーを取得する方法がわかりません。このようなもの:

SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass;

それを行う方法はありますか、それとも不可能ですか?ガベージ コレクターにオブジェクトを処理するように指示するにはどうすればよいですか? 新しいガベージ コレクション オブジェクトを作成し、フィールドごとにデータをコピーする必要がありますか?

ティア、

4

2 に答える 2

5

いいえいいえいいえ いいえ!!!

これ

struct SOMESTRUCT
{
    public SomeClass object_ref;
}

参照を構造体に格納する正しい方法です。

あなたが書いたコードと受け入れられた答えは、100% 壊れています。

によって返されるアドレスは、が無傷GC.AddrOfPinnedObject(GCHandle)の場合にのみ有効です。GCHandleに電話してはいけません。 を回収GCHandle.Freeさせてはいけません。GCHandleあなたのコードでは、アドレスは保存する時点ですでに無意味です。

ただし、参照型の変数を使用して、ガベージ コレクション中のポインターの管理を .NET に任せるべきです。そうすれば、フープを飛び越える必要はありません。マネージ オブジェクトのアドレスを取得する唯一の理由は、返された後にポインターを保存する既存のネイティブ DLL 関数に渡す場合です。たとえば、OpenGL バッファ配列では必要です。他の C# メソッドを呼び出すときは、必要ありません。

SOMESTRUCT が実際に、言及していない DLL 関数によって使用されるネイティブ データ型である場合は、確実に有効にしておく必要がありますGCHandle。が存在する限り、GCHandle取得したポインターは有効なままです。

于 2011-01-15T17:08:32.337 に答える
2

返されたポインタを構造体にキャストし直すということですか?

に似ている:

lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO));

ここで、lvHitTestInfoは構造体であり、lpはポインターです。

または私はあなたの質問を正しく理解していませんでした。たぶんあなたはもっと説明することができます(より完全なコードサンプル)。

于 2010-06-29T14:36:53.283 に答える