1

4 つの出力パラメーターを返すこの関数を含む C ライブラリがあります。

void __declspec(dllexport) demofun(double a[], double b[], double* output1, double* output2, double res[], double* output3)

そして、関数を呼び出す C# ラッパーを作成しました。

namespace cwrapper
{
    public sealed class CWRAPPER
    {    
        private CWRAPPER() {}

        public static void demofun(double[] a, double[] b, double output1,
                            double output2, double[] res, double output3)
        {   // INPUTS: double[] a, double[] b
            // OUTPUTS: double[] res, double output1, double output2
            // Arrays a, b and res have the same length
            // Debug.Assert(a.length == b.length)

            int length = a.Length;
            CWRAPPERNative.demofun(a, b, length, ref output1, ref output2,
                         res, ref output3);
        }
    }

    [SuppressUnmanagedCodeSecurity]
    internal sealed class CWRAPPERNative
    {
        private CWRAPPERNative() {}

        [DllImport("my_cwrapper.dll", CallingConvention=CallingConvention.Cdecl,
             ExactSpelling=true, SetLastError=false)]
        internal static extern void demofun([In] double[] a, [In] double[] b,
                             int length, ref double output1, ref double output2,
                             [Out] double[] res, ref double output3);
    }
}

CWRAPPERNative.demofunメソッドを呼び出すと、すべて正常に動作します。ただし、CWRAPPER.demofunメソッドを呼び出すと、 のみがdouble[] res正しく渡されます。出力パラメータoutput1output2およびoutput3は、呼び出し後に変更されません。

// ...
// Initializing arrays A and B above here

double[] res = new double[A.Length];
double output1 = 0, output2 = 0, output3 = 0;

// Works partially: output1 to 3 unchanged
CWRAPPER.demofun(A, B, output1, output2, res, output3);

// Works correctly: all outputs are changed
CWRAPPERNative.demofun(A, B, A.Length, ref output1, ref output2, res, ref output3);

ポインター引数を間違ってマーシャリングしていると推測していますが、修正方法がわかりません。誰でも解決策を知っていますか?ありがとう!

4

2 に答える 2

1

demofun内で参照によって値を渡すのを忘れています。

public static void demofun(double[] a, double[] b, ref double output1,
   ref double output2, double[] res, ref double output3)

値はメソッド内で変更されていますが、元の呼び出し元に変更されていません。

于 2012-12-10T04:53:48.997 に答える
0

すべてのdoubleパラメータCWRAPPER.demofunは不揮発性です。つまり、関数によって値を変更することはできません。これを修正するには、次のような変更が必要です。

public static void demofun(double[] a, double[] b,
  out double output1, out double output2, double[] res, out double output3)

しかし、別の問題があります。C 関数の 5 番目のパラメーターdouble res[]は入力パラメーターですが、P/Invoke 宣言には[Out] double[] res(出力パラメーター) があります。P/Invoke 宣言を次のように書き直します。

[DllImport("my_cwrapper.dll", CallingConvention=CallingConvention.Cdecl,
  ExactSpelling=true, SetLastError=false)]
static extern void demofun([In] double[] a, [In] double[] b, [In] int length,
  [Out] double output1, [Out] double output2, [In] double[] res, [Out] double output3);

outパラメータを使用したメソッドの実装例。OutOutTesterパラメータを持つメソッドはout、値を直接割り当てる必要がないことを示しています。

public static void OutTester(out int a)
{
    a = 1;
}

public static void OutOutTester(out int a, out int b)
{
    OutTester(out a);
    b = 1;
}
于 2012-12-10T05:08:49.837 に答える