2010-09-05 74 views
3

Im在非托管dll函数swe_calc_ut上使用P/invoke。P /调用System.ExecutionEngineException当传递数组作为参考/输出

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

请参阅http://stackoverflow.com/questions/2218444/when-passing-a-managed-byte-array-through-pinvoke-to-be-filled-in-by-win32-doe/2218600#2218600 – 2010-09-05 09:26:19

+0

您需要提供有关非托管函数的更多信息,更好的代码示例从C++调用此函数。为什么xx被声明为double **? double *对于一维数组就足够了。也许swe_calc_ut分配这个数组?什么是数组大小?这个数组是如何发布的?关于serr参数也是一样。没有这些细节,就不可能写出正确的PInvoke调用。 – 2010-09-05 09:44:50

回答

6

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

5

这是C语言的约定,您通过传递指向数组第一个元素的指针来传递数组。所以一个双[]已经编组为double*。当您使用输出或ref关键字时,您告诉编组器,该函数返回一个指向新阵列的指针double**

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

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