C#プロジェクトにインポートされたC++のライブラリから呼び出される関数があります
配列へのポインタを求めていると思います。しかし、それを機能させる方法がわかりません。
これがそれが求めているものですfunction(float*, float*);
しかし、私が次のようなことをした場合
float[] f = {};
float[] f1 = {};
function(f,f1);
無効な引数があると表示されます。
C#プロジェクトにインポートされたC++のライブラリから呼び出される関数があります
配列へのポインタを求めていると思います。しかし、それを機能させる方法がわかりません。
これがそれが求めているものですfunction(float*, float*);
しかし、私が次のようなことをした場合
float[] f = {};
float[] f1 = {};
function(f,f1);
無効な引数があると表示されます。
これが経由でインポートされたメソッドである場合はDLLImport()
、配列ポインタを型付き配列に置き換えるだけです。
だから署名:
[DLLImport("some.dll")]
SomeMethod(int* a, float* b)
になる
[DLLImport("some.dll")]
SomeMethod(int[] a, float[] b)
これは、元のc /c++メソッドが配列を予期していたことを前提としていることに注意してください。ポインタが配列を参照することを意図していない場合、これは機能しません。
float *は、C#のfloatポインター型です。
関数がfloatポインター引数(float *)を期待している場合、関数はポインターで動作すると推定される必要があり、ポインター演算が含まれる可能性があります。したがって、その署名を保持することが重要です。
C#でfloat配列をfloatポインター(float *)として渡すには、安全でないコンテキストでメモリ内の配列を固定/修正して、機能を維持するために関数に渡すことができる配列へのポインターを取得する必要があります。
unsafe
{
fixed (float* ptr_f = f) //or equivalently "... = &f[0]" address of f[0]
fixed (float* ptr_f2 = f2) //or equivalently "... = &f2[0]" address of f2[0]
{
function( ptr_f, ptr_f2 );
}
}
また、アセンブリを安全でないものとしてマークする必要があります([プロジェクトのプロパティ]>[ビルド]タブ>[安全でないコードを許可する]チェックボックス)。
呼び出されたC++関数が何を期待しているかを正確に知る必要があります。
C(およびC ++)では、これらの関数シグネチャはすべて、すべての目的と目的でまったく同じです。
void foo( float *x , float *y ) ;
void foo( float *x , float y[] ) ;
void foo( float x[] , float *y ) ;
void foo( float x[] , float y[] ) ;
それらはすべて2つの引数を取り、それぞれに型の変数への(のアドレスを含む)ポインタが含まれていますfloat
。そして、これらの式はすべて、C /C++ではまったく同じです。
float x[] ;
float *y ;
float r1 = *(x+37) ; // all evaluate to the zero-relative
float r2 = x[37] ; // 37th element of the array.
float r3 = *(y+37) ;
float r4 = y[37] ;
*x
フェッチします。float
x
*(x+n)
ます。結果のアドレスにある値をフェッチします。n
sizeof(float) * n
float
x[n]
は、ポインター式とまったく同じ*(x+n)
です。また、C / C ++の配列には、そのサイズを説明するメタデータが関連付けられていないため、呼び出された関数が何を期待しているかを正確に知る必要があります。
通常、呼び出し元がポイントを参照解除して値を設定できるようにするために、ポインター(参照による呼び出し)を渡します。これは、C#ref
やout
キーワードに相当します。
float x ;
float y ;
Foo( ref x , ref y ) ; // the callee MAY, but is not REQUIRED to set a value before returning to the caller.
Bar( out x , out y ) ; // the callee MUST set a value before returning to the caller.
関数が使用しているイディオムは、配列を見つけるために常に使用されますが、通常、サイズも渡されます。
void foo( float *array , int array_length ) ;
珍しいことではありませんが、関数が配列がゼロ以外の数値のリストであることを期待している場合は、CスタイルのNULで終了する文字列のようなものになります。たとえば、関数のシグネチャが与えられます。
float compute_mean( float *Xs ) ;
このように呼び出されることが期待されることは珍しいことではありません。
float Xs[] = { 3.0 , 2.5 , 9.8 , 7,5 , 0 , } ;
float mean = compute_mean( Xs ) ;
そして、次のような定義になります。
float compute_mean( float *Xs )
{
float n = 0.0 ;
float sum = 0.0 ;
float mean ;
while ( *p )
{
++n ;
sum += *p++ ;
}
mean = n > 0 ? sum / n : 0.0 ;
return mean ;
}
したがって、呼び出すメソッドのセマンティクスを知る必要があります。
お役に立てれば。
これはC#ではまったく機能しません。C#でC / C ++ライブラリをインポートする場合はIntPtr
、float*の代わりに使用する必要があります。いくつかの例についてはこちらを参照してください:CからC#へのfloat *
浮動小数点ポインターを要求しています(IEEE浮動小数点値を含むメモリ内のポイントのマシンアドレス)。C#ではポインターの管理された使用が許可されていないため、 IntPtr変数を作成してC++に渡す必要があります。働き。
注:呼び出されたからといって、IntPtr
それが整数へのポインタにすぎないという意味ではありません。Intは、すべてのポインターが整数であるためです。それは何へのポインタでもありえます。