将数组作为 ref/out 传递时 P/invoke System.ExecutionEngineException

发布于 2024-09-17 18:01:59 字数 704 浏览 6 评论 0原文

我在非托管 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 新手,所以我可能犯了一个愚蠢的错误。我认为这一定是数组,因为早些时候当我意外地按值传递它们时,我没有收到错误。我非常感谢你的帮助。

Im using an P/invoke on an unmanaged dll function swe_calc_ut.

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

Parameter xx is meant to be an "array of 6 doubles for storing the result", and parameter serr a "character string to return error messages"


my c# code is as follows.

[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);

Now when i execute the function swe_calc_ut function i get the error "Exception of type 'System.ExecutionEngineException' was thrown.". I'm new to P/invoke so i'm probably making a stupid mistake. I thought it must be the arrays since earlier when i passed them by value accidentally i did not get an error. I'd really appreciate your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

惯饮孤独 2024-09-24 18:01:59

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

You don't have to use out or ref here. In fact, lose both of them. And preallocate both arrays to the desired size in C#.

笙痞 2024-09-24 18:01:59

这是 C 语言的约定,通过传递指向数组第一个元素的指针来传递数组。因此 double[] 已经被编组为 double*。当您使用 outref 关键字时,您告诉编组器该函数返回一个指向 new 数组的指针,一个 double **。

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

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

It is a convention of the C language, you pass an array by passing a pointer to the first element of the array. So a double[] is already marshaled as a double*. When you use the out or ref keyword, you tell the marshaller that the function returns a pointer to a new array, a double**.

The function does not create a new array, it requires the client to pass an array that's large enough to receive the result. Therefore, neither the out nor the ref annotation is correct. The serr argument should be declared as StringBuilder btw.

The function is very dangerous since there is no way for the client to say how large an array it created. Particularly a problem with the serr argument. A detailed error message is prone to overrun the end of the array and that will destroy the garbage collected heap. Nothing you can do but pass a very large array (i.e. StringBuilder with a large Capacity) and keep your fingers crossed. Buffer overruns are the preferred attack vector for malware authors. Not likely to be abused in a managed program, it will just crash the app with FEEE.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文