[英]Marshalling output pointers during P/Invoke calls from C# to C
我有一個帶有此函數的C庫,該函數返回4個輸出參數:
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
可以正確傳遞。 調用后,輸出參數output1
, output2
和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);
我猜想我錯誤地整理了指針參數,但是我無法弄清楚解決方法。 有人知道解決方案嗎? 謝謝!
您忘記了在demofun內部通過引用傳遞值:
public static void demofun(double[] a, double[] b, ref double output1,
ref double output2, double[] res, ref double output3)
值在方法內部更改,但未修改為原始調用方。
CWRAPPER.demofun
所有double
參數都是非易失性的,即,該值不能由該函數更改。 要解決此問題,您需要進行如下更改:
public static void demofun(double[] a, double[] b,
out double output1, out double output2, double[] res, out double output3)
不過還有另一個問題。 C函數的第五個參數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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.