error C2664: 'innercppclass::getnum' : cannot convert parameter 1 from 'float' to 'float &'
An object from the gc heap (a dereferenced gc pointer) cannot be converted to a native reference
対処しているエラーを文書化するのを忘れました。これはあなたが見たものです。これは完全に設計によるものであり、マネージ コードの動作の基本です。
マネージ関数の float% 引数は、ref クラスのフィールドのように、マネージ オブジェクトへの内部ポインターにすることができます。float& 参照は、実行時に生のアンマネージ ポインターになり、float 値を指します。これにより、呼び出し先は値を更新できます。どちらも実行時の単純なポインターです。唯一の違いは、ガベージ コレクターが内部ポインターを認識できるが、アンマネージ ポインターを認識できないことです。ジッターはマネージ ポインターを探す場所を示しますが、ネイティブ C++ 関数はジッターされていないため、そのような助けにはなりません。
したがって、アンマネージ ポインターに内部ポインター値を割り当てることは可能です。ただし、ネイティブ コードの実行中にガベージ コレクターが実行されると、非常にやっかいなことが起こります。プログラム内の他のスレッドがメモリを割り当てると、GC が発生する可能性があることに注意してください。GC が行う重要なことの 1 つは、ヒープを圧縮することです。これは、マネージド オブジェクトをコレクションの一部として移動します。非常に望ましい特性であり、ヒープの穴を取り除き、参照の局所性を改善することでマネージド コードを高速にします。問題は、ネイティブ コードが、フロートが移動される前にあった場所へのポインタを保持していることです。また、ポインターを介して書き込み、浮動小数点値を更新すると、GC ヒープが破損します。
GC がネイティブ コードがこれを行うのを止める方法はありません。ポインター値がメモリ内のどこにあるかがわからないため、GC は更新できません。内部ポインタにはそのような問題はありませんが、ネイティブ参照には解決できない問題があります。
そのため、コンパイラは、遅かれ早かれ (通常は後で) 完全に診断不能なヒープ損傷でプログラムをクラッシュさせないようなコードを生成することはできない、と文句を言います。回避策は既に見つかりました。GC ヒープではないストレージの場所からポインターを生成する必要があります。スタックは問題なく、ローカル変数は移動しません:
void Managed::getnum(float% num) {
float temp;
innercppclass::getnum(temp);
num = temp;
}
それ以外の場合は、void getnum(float%) を float getnum() に変換するときに同様に記述する種類のコードを記述します。またはより一般的にマネージド コードでは、プロパティ ゲッター:
property float num {
float get() {
float temp;
innercppclass::getnum(temp);
return temp;
}
}
それについて他にできることは何もありません。これは非常に基本的な制限です。