将数组作为ref / out传递时,调用System.ExecutionEngineException

时间:2010-09-05 09:21:12

标签: c# .net pinvoke dllimport

我在非托管dll函数swe_calc_ut上使用P / invoke。

int swe_calc_ut(double tjd_et, int ipl, int iflag, double *xx, char *serr)

参数xx是“用于存储结果的6个双精度数组”,参数serr是“返回错误消息的字符串”


我的c#代码如下。

[DllImport("swedll32.dll")]
private static extern int swe_calc_ut(double tjd_ut, int ipl, int iflag, out double[] xx, out char[] serr);

double jul_day_UT=22000;
int p=3;
int iflag=64 * 1024;
double[] arr;
char[] serr;

int x = swe_calc_ut(jul_day_UT, p, iflag , out arr, out serr);

现在当我执行函数swe_calc_ut函数时,我得到错误“抛出了类型'System.ExecutionEngineException'的异常。”。我是P / invoke的新手,所以我可能犯了一个愚蠢的错误。我认为它必须是数组,因为早些时候我偶然通过值传递它我没有得到错误。我非常感谢你的帮助。

2 个答案:

答案 0 :(得分:6)

您不必在此使用outref。事实上,失去了他们两个。并在C#中将两个数组预分配到所需的大小。

答案 1 :(得分:5)

它是C语言的约定,通过将指针传递给数组的第一个元素来传递数组。所以double []已经被封送为double*。当您使用 out ref 关键字时,您告诉编组人员该函数返回指向 new 数组的指针,{{1} }。

该函数创建一个新数组,它要求客户端传递一个足够大的数组来接收结果。因此,out和ref注释都不正确。应该将serr参数声明为StringBuilder btw。

该函数非常危险,因为客户端无法说出它创建的数组有多大。特别是 serr 参数的问题。详细的错误消息很容易超出数组的末尾,这将破坏垃圾收集堆。除了传递一个非常大的数组(即具有大容量的StringBuilder)并且保持手指交叉之外,你什么也做不了。缓冲区溢出是恶意软件作者的首选攻击媒介。不太可能在托管程序中被滥用,它只会使应用程序崩溃。