我在非托管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的新手,所以我可能犯了一个愚蠢的错误。我认为它必须是数组,因为早些时候我偶然通过值传递它我没有得到错误。我非常感谢你的帮助。
答案 0 :(得分:6)
您不必在此使用out
或ref
。事实上,失去了他们两个。并在C#中将两个数组预分配到所需的大小。
答案 1 :(得分:5)
它是C语言的约定,通过将指针传递给数组的第一个元素来传递数组。所以double []已经被封送为double*
。当您使用 out 或 ref 关键字时,您告诉编组人员该函数返回指向 new 数组的指针,{{1} }。
该函数不创建一个新数组,它要求客户端传递一个足够大的数组来接收结果。因此,out和ref注释都不正确。应该将serr参数声明为StringBuilder btw。
该函数非常危险,因为客户端无法说出它创建的数组有多大。特别是 serr 参数的问题。详细的错误消息很容易超出数组的末尾,这将破坏垃圾收集堆。除了传递一个非常大的数组(即具有大容量的StringBuilder)并且保持手指交叉之外,你什么也做不了。缓冲区溢出是恶意软件作者的首选攻击媒介。不太可能在托管程序中被滥用,它只会使应用程序崩溃。