ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 使用.NET Native构建时,参数不会传递到x86上的非托管DLL

2019-05-19 15:03:27  阅读:253  来源: 互联网

标签:c visual-studio-2015 win-universal-app dllimport net-native


我正在构建一个Windows 10通用应用程序(手机平板电脑)库.
在解决方案中,我有C dll项目,它构建了从C#调用的非托管my.dll.
DLL导出如下:

// === C++ ===
typedef struct { int f1; uint32_t f2; } R;
// A and B are also structures.
MY_EXPORT R the_function( A *a, const B *b, const uint8_t *c );

// === C# ===
[DllImport( "my.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl )]
extern static R the_function(A a, B b, byte[] c);

[StructLayout( LayoutKind.Sequential )]
internal struct R
{
    public int f1;  // Actually a enum but it shouldn’t matter.
    public uint f2_id;
} 

internal struct A
{
    IntPtr nativePtr;
}

internal struct B
{
    IntPtr nativePtr;
}

该测试应用程序适用于ARM和X64平台.如果未选中“使用.NET Native工具链编译”,它将在X86上运行.

如果选中“使用.NET Native工具链编译”,则说明访问冲突,非托管DLL在X86上崩溃.我可以在Debug和Release版本中重现.

使用调试器时,我发现参数的传递方式存在错误.
在C#方面,在一些编译器生成的C#代码中有一行如下:

unsafe___value = global::McgInterop.my_PInvokes.the_function( a, b, unsafe_c );

在调试器中,我确认参数是正确的.

在C方面,值是错误的.
b的值是a中传递的值,c的值是b中传递的值.

我试图创建一个简约的例子,但失败了,它工作正常.
my.dll导出了100个导出的__cdecl方法,它是一个大型的跨平台C SDK,我正在努力将其带到Windows 10平台,看起来其他方法工作正常.

有什么想法在这里发生了什么?或者至少如何隔离问题?提前致谢.

更新:好的,这是一个最小的repro.

非托管代码:

typedef struct
{
    int f1;
    DWORD f2;
} R;

R __cdecl nativeBug( int a, int b )
{
    CStringA str;
    str.Format( "Unmanaged DLL: a = %i, b = %i\n", a, b );
    ::OutputDebugStringA( str );
    R res
    {
        11, 12
    };
    return res;
}

C#store app:

[StructLayout( LayoutKind.Sequential )]
struct R
{
    public int f1;
    public uint f2;
}

[DllImport( "NativeBugDll.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl )]
extern static R nativeBug( int a, int b );

private void Page_Loaded( object sender, RoutedEventArgs e )
{
    App.Current.UnhandledException += app_UnhandledException;
    R r = nativeBug( 1, 2 );
    Debug.WriteLine( "Result: f1={0}, f2={1}", r.f1, r.f2 );
}

private void app_UnhandledException( object sender, UnhandledExceptionEventArgs e )
{
    Debug.WriteLine( "Unhandled exception: " + e.Message );
}

没有.NET Native的调试输出很好:

Unmanaged DLL: a = 1, b = 2
Result: f1=11, f2=12

这是.NET Native build的调试输出:

Unmanaged DLL: a = 91484652, b = 1
Unhandled exception: Object reference not set to an instance of an object.
STATUS_STACK_BUFFER_OVERRUN encountered

然后视觉工作室完全挂起.

即使使用.NET Native,X64构建也能正常工作.

解决方法:

哎呀!看起来.NET Native中可能存在错误.我已经请微软的人来看一看.如果您想与我们联系,请随时发送电子邮件至dotnetnative@microsoft.com.

我会更新这个更新.

编辑:
因此,如果本机函数返回这样的结构,肯定存在一个真正的错误.优化器最终处于这样一种状态,它在两个参数之后将一个额外的参数推送到堆栈,这就是造成错误的原因.

我已经打开了一个错误,我们将修复VS的Update 2.

C#:

[StructLayout(LayoutKind.Sequential)]
struct R
{
   public int f1;
   public int f2;
    }

[DllImport("DllImport_NativeDll.dll")]
extern static R nativeBug(int a, int b);

public static void Run()
{
        R r = nativeBug(1, 2);
}

本机:

typedef struct
{
    int f1;
    int f2;
} R;

extern "C" __declspec(dllexport) R nativeBug(int a, int b)
{
    R res
    {
        11, 12
    };
    return res;
}

代码生成:

00f1766b 8b55fc          mov     edx,dword ptr [ebp-4]
00f1766e 52              push    edx
00f1766f 8b45f8          mov     eax,dword ptr [ebp-8]
00f17672 50              push    eax
00f17673 8d4ddc          lea     ecx,[ebp-24h]
00f17676 51              push    ecx <-- Bonus and unfortunate push
00f176ab ff1524b4d200    call    dword ptr [PInvokeAndCom!_imp__nativeBug (00d2b424)]

标签:c,visual-studio-2015,win-universal-app,dllimport,net-native
来源: https://codeday.me/bug/20190519/1136140.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有