Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在传递时,什么会导致P/Invoke参数出错?_C#_Windows_Uwp_Arm_Pinvoke - Fatal编程技术网

C# 在传递时,什么会导致P/Invoke参数出错?

C# 在传递时,什么会导致P/Invoke参数出错?,c#,windows,uwp,arm,pinvoke,C#,Windows,Uwp,Arm,Pinvoke,这是一个专门在ARM上发生的问题,而不是在x86或x64上。我有一个用户报告了这个问题,并且能够通过Windows IoT在Raspberry Pi 2上使用UWP复制它。我以前在不匹配的调用约定中见过这种问题,但是我在P/Invoke声明中指定了Cdecl,并且我尝试在本机端显式添加_Cdecl,结果相同。以下是一些信息: p/Invoke声明(): C#structs(): C标头()中的函数 FLASCICRESULTE可能会引起一些问题,因为它是由值返回的,并且在本地端上有一些C++的

这是一个专门在ARM上发生的问题,而不是在x86或x64上。我有一个用户报告了这个问题,并且能够通过Windows IoT在Raspberry Pi 2上使用UWP复制它。我以前在不匹配的调用约定中见过这种问题,但是我在P/Invoke声明中指定了Cdecl,并且我尝试在本机端显式添加_Cdecl,结果相同。以下是一些信息:

p/Invoke声明():

C#structs():

C标头()中的函数

FLASCICRESULTE可能会引起一些问题,因为它是由值返回的,并且在本地端上有一些C++的东西?

本机端的结构具有实际信息,但对于C API,定义了FLEncoder。在x86和x64上调用上面的方法时,一切都很顺利,但在ARM上,我观察到以下几点。第一个参数的地址是第二个参数的地址,第二个参数为null(例如,当我在C#端记录地址时,我得到了,例如0x054f59b8和0x0583f3bc,但在本机端,参数是0x0583f3bc和0x00000000)。什么会导致这种故障问题?有人有什么想法吗,因为我被难住了

以下是我运行以复制的代码:

unsafe {
    var enc = Native.FLEncoder_New();
    Native.FLEncoder_BeginDict(enc, 1);
    Native.FLEncoder_WriteKey(enc, "answer");
    Native.FLEncoder_WriteInt(enc, 42);
    Native.FLEncoder_EndDict(enc);
    FLError err;
    NativeRaw.FLEncoder_Finish(enc, &err);
    Native.FLEncoder_Free(enc);
}

运行C++程序,以下工作精细:

auto enc = FLEncoder_New();
FLEncoder_BeginDict(enc, 1);
FLEncoder_WriteKey(enc, FLSTR("answer"));
FLEncoder_WriteInt(enc, 42);
FLEncoder_EndDict(enc);
FLError err;
auto result = FLEncoder_Finish(enc, &err);
FLEncoder_Free(enc);
这种逻辑可能会触发最新版本的崩溃,但不幸的是,我还没有弄清楚如何通过Nuget可靠地提供本机调试符号,以便能够逐步完成(只有从源代码构建所有东西似乎才能做到这一点……)所以调试有点尴尬,因为本机组件和托管组件都需要构建。如果有人想尝试的话,我愿意接受关于如何使这更容易的建议。但是,如果有人曾经经历过这种情况,或者对为什么会发生这种情况有任何想法,请添加一个答案,谢谢!当然,如果有人想要一个复制案例(无论是一个不提供源代码步进的易于构建的案例,还是一个提供源代码步进的难以构建的案例),那么请留下评论,但如果没有人使用它,我不想经历一个制作过程(我不确定在实际ARM上运行Windows的东西有多流行)

编辑有趣的更新:如果我在C#中“伪造”签名并删除第二个参数,那么第一个参数通过OK

编辑2第二个有趣的更新:如果我将大小的C#FLSliceResult定义从
uintptpr
更改为
ulong
,则参数输入正确…这没有意义,因为ARM上的
size\u t
应该是无符号int

编辑3
[StructLayout(LayoutKind.Sequential,Size=12)]
添加到C#中的定义中也可以实现这一点,但为什么?C/C++中的SIEZOF(FLLSICEESULTE)对于这个体系结构返回8。在C#中设置相同的大小会导致崩溃,但将其设置为12会使其正常工作

<> > >编辑4 < /Sturi>我最小化了测试用例,这样我也可以编写C++测试用例。在C uuup中失败,但在C++ UWP中成功。 < > > >编辑5 <强>是C++和C语言的分解指令,用于比较(虽然C不确定要花多少,所以我在占用太多的地方出错)

EDIT 6进一步的分析表明,在“良好”运行期间,当我说谎并说结构是C#上的12字节时,返回值被传递到寄存器r0,另外两个参数通过r1、r2传入。但是,在错误运行中,这会被转换,以便两个参数通过r0、r1进入,并且返回值位于其他地方(堆栈指针?)

编辑7我咨询了。我发现了这样一句话:“一个大于4字节的复合类型,或者其大小不能由调用方和 被调用方存储在内存中,其地址在调用函数时作为额外参数传递(§5.5, 规则A.4)。用于结果的内存可以在函数调用期间的任何时候修改。“这意味着传递到r0是正确的行为,因为额外参数意味着第一个参数(因为C调用约定没有指定参数数量的方法)。我想知道CLR是否将此与另一条关于基本64位数据类型的规则相混淆:“需要一种双字大小的基本数据类型(例如,长-长、双和64位容器化向量) 在r0和r1中返回。“


编辑8好的,有很多证据表明CLR做了错误的事情,所以我提交了一份报告。我希望有人在所有自动机器人在回购协议上发布问题时注意到这一点:-S.

我在GH上提交的问题已经存在了相当长的一段时间。我相信这种行为只是一个bug,不需要花费更多的时间来研究它。

评论不用于扩展讨论;这场对话已经进行了0.60次投票,而且没有提供任何悬赏……这就是weird@MauricioGraciaGutierrez我想我可以用“这是JIT引擎中的一个bug”来回答这个问题(我想大多数人来这里投票是因为他们对bug的解决感兴趣)听起来像是印度的大问题和小问题。。。这个问题是否可以关闭,因为它似乎是一个bug?
FLSliceResult FLEncoder_Finish(FLEncoder, FLError*);
unsafe {
    var enc = Native.FLEncoder_New();
    Native.FLEncoder_BeginDict(enc, 1);
    Native.FLEncoder_WriteKey(enc, "answer");
    Native.FLEncoder_WriteInt(enc, 42);
    Native.FLEncoder_EndDict(enc);
    FLError err;
    NativeRaw.FLEncoder_Finish(enc, &err);
    Native.FLEncoder_Free(enc);
}
auto enc = FLEncoder_New();
FLEncoder_BeginDict(enc, 1);
FLEncoder_WriteKey(enc, FLSTR("answer"));
FLEncoder_WriteInt(enc, 42);
FLEncoder_EndDict(enc);
FLError err;
auto result = FLEncoder_Finish(enc, &err);
FLEncoder_Free(enc);