0

ポインターパラメーターを使用して出力パラメーターを取得できる適切な署名/マーシャル属性は何ですか? これまでのところ、私はこれを試しました:

// Function to calculate the norm of vector. !0 on error.
// int err_NormVec(int size, double * vector, double * norm)
[DllImport("vectors.dll")]
int err_NormVec(int size, double[] vector, ref double norm)

前のアプローチでは、値が C から .NET に戻されません。また、固定された GCHandle を IntPtr シグネチャと共に使用しようとしました。

[DllImport("vectors.dll")]
int err_NormVec(int size, double[] vector, IntPtr norm)

public void doSomething()
{
   double norm = 0;
   // ...
   GCHandle handle = GCHandle.Alloc(norm, GCHandleType.Pinned);
   int status = err_NormVec(vector.Lenght, vector, handle.AddrOfPinnedObject());
   // ... clean gchandle, check status and so on
}

この場合、元の基準ではなく、GCHandle.Target で値が返されました。これは迷惑です。単なるコピーではなく、標準の intptr を固定できるようにしたいと考えています。

ポインターを使用して値を返すための適切なシグネチャは何ですか? IntPtr を int 値に取得するサポートされている方法はありますか?

4

1 に答える 1

1

これは私にとってはうまくいきます(そうあるべきです):

//C++ DLL (__stdcall calling convention)
extern "C" __declspec(dllexport) void Foo(double *result) {
    *result = 1.2;
}

//C#    
class Program
{
    [DllImport( "Snadbox.dll", CallingConvention=CallingConvention.StdCall )]
    static extern void Foo( ref double output );

    static void Main( string[] args )
    {
        double d = 0;           
        Foo( ref d );

        Console.WriteLine( d ); // prints "1.2"         
    }
}

doubleusingrefキーワードを渡すだけで十分です。ですから、実装に何か問題がある(または誤解されている)と私は信じさせられます。実装を投稿していただけますか?

また、デフォルトの呼び出し規約(cdecl)を使用してC ++バージョンを構築している可能性がありますが、.NETはを使用していますStdCall。これらが並んでいることを確認しましたか?混合するとクラッシュする可能性がありますが、保証はありません。たとえば、私の例では、C ++側をに変更するとcdecl、outパラメーターは0として読み戻されます。

于 2012-04-11T18:53:24.673 に答える