2011-02-01 13 views
1

C++コード(LPSolve、http://lpsolve.sourceforge.net/5.5/を参照)からコンパイルされたDLLをC#コードから使用します。 APIを使用して線形計画モデルを作成し、それを解決します。私は、このような関数を呼び出すと、私はマネージコードで作成されたint型と配列は(C#コードで)スコープを出るとき、私は、何が起こるか、memorywiseを疑問に思ってDLL内の関数を呼び出すとどうなりますか

[DllImport("lpsolve55.dll", SetLastError = true)] 
public static extern bool add_columnex 
      (int lp, int count, double[] column, int[] rowno); 

:私は、次のような関数を呼び出します。彼らはガベージコレクションの対象となりますか?これはC++コードの意味ですか?あるいは、不適格であり、その場合、なぜですか?

答えて

2

関数プロトタイプでは古いデータ型と配列は使用されていないため、これらの値のメモリは固定され、ネイティブコードが直接データに作用します。関数が復帰すると、メモリは固定解除され、ガベージコレクトされます。

つまり、スコープから離れることはありません。

C++コードでは、データを格納する必要がある場合は、渡されたデータのコピーを取得し、そのメモリ自体を管理する必要があります。

1

あなたのアプリが(ガベージコレクションを過ぎて)しばらく使った後にAccessViolationExceptionでクラッシュしない場合は、アンマネージドコードが渡された配列要素のコピーを作成したと見なすことはかなり安全です。これは普通のことですが、そうでなければネイティブコードからライブラリを使用することは非常に難しいでしょう。また、モデルをクリアまたは再初期化し、メモリを解放する必要があるAPI関数が必要です。

2

私はニックが基本的な部分をカバーしていると思いますが、これはちょっとした情報を追加することです。 int/doubleの配列はblittable型(管理された/管理されていない世界で同じレイアウトを持つ型)とみなされます。これらは通常マーシャリング時に固定されます。だから、あなたはGCについて知る必要はありません。また、あなたが行ったことは、配列を値渡しすることを示します。そのような場合、marshallerはこれをInパラメータとして扱います。アンマネージドdllは配列の値を更新する場合、イン/アウトパラメータとしてマークすることをお勧めします例えば[In, Out]double[] column)。

  1. blittable型と非blittable型タイプ: http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx
  2. のコピーとピンニング:http://msdn.microsoft.com/en-us/library/23acw07k.aspx
  3. マーシャリングアレイ:詳細情報についてはhttp://learning.infocollections.com/ebook%202/Computer/Programming/General/Programming.With.Microsoft.Dot.NET/LiB0948.htm
0

CまたはC++関数は、このようなプロトタイプを持っています:

bool add_columnex(int lp, int count, double[] column, int[] rowno); 

Thパラメータlpとcountは値渡しです。パラメータ列とrownoも値渡しされますが、実際のデータは参照渡しとなります。関数add_columnexは列とrownoを逆参照する必要があります。この逆参照は、関数呼び出し中にのみ許可されます。関数が復帰すると、これらのパラメータは範囲外です。脱融解の種類は、インタフェースの契約に含まれていなければなりません。

すべての引数がスコープから外れ、関数が呼び出し後に何かを行うことができるという意味はありません。この関数が引数のコピー、すなわち二重配列またはrowno配列のアドレスを格納する場合、これは契約によって許可されなければならない。その場合、あなたは困ってしまうでしょう。より良い契約は、関数が逆参照されたデータをコピーする必要があるということです。

関連する問題