C# P/invoke System.executionEngineeException当数组作为ref/out传递时
我在非托管dll函数swe_calc_ut上使用p/invokeC# P/invoke System.executionEngineeException当数组作为ref/out传递时,c#,.net,pinvoke,dllimport,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 ip
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.executionEngineeException'的异常”。我是P/invoke新手,所以我可能犯了一个愚蠢的错误。我想它一定是数组,因为早些时候我无意中通过值传递它们时,没有得到错误。非常感谢您的帮助。您不必在这里使用
out
或ref
。事实上,他们两个都失去了。并将两个数组预先分配到C#中所需的大小。这是C语言的惯例,通过传递指向数组第一个元素的指针来传递数组。因此,double[]已被封送为double*
。当您使用out或ref关键字时,您告诉封送拆收器该函数返回指向新数组的指针,即double**
该函数不创建新数组,它要求客户端传递一个足够大的数组来接收结果。因此,out和ref注释都不正确。serr参数应声明为StringBuilder btw
该函数非常危险,因为客户端无法说出它创建的数组有多大。特别是serr参数的问题。详细的错误消息很容易溢出数组的末尾,这将破坏垃圾收集堆。除了传递一个非常大的数组(即具有大容量的StringBuilder)并保持交叉之外,您什么也做不了。缓冲区溢出是恶意软件作者首选的攻击向量。不太可能在托管程序中被滥用,它只会用Fee来破坏应用程序。参见您需要提供更多关于非托管函数的信息,更好的代码示例从C++调用这个函数。为什么xx被声明为双**?对于一维数组,double*就足够了。也许swe_calc_ut分配了这个数组?什么是数组大小?如何释放此阵列?serr参数也是如此。没有这些细节,就不可能写出正确的PInvoke调用。