C# PInvoke:当我按“F5”在 VS 中运行时,外部 C++ api 运行良好,但在外部无法运行

问题描述 投票:0回答:1

当我按“F5”在 Visual Studio 2022 中运行我的 C# 应用程序时,MDA 建议使用 PInvokeStackImbalance,但如果我忽略 MDA 并按 F5 继续,则效果很好,C++ api 返回 1

但是如果我直接在 Windows 中运行我的应用程序,则不会出现异常并且 api 返回 0

平台设置为Release - x86,我确认文件夹是正确的。 我的C#项目是.NET Framework 4.7.2,winform应用程序。

希望有人可以帮助我解决 PInvokeStackImbalance 问题 - 我知道修复它可能会使我的应用程序在 VS 之外运行。
而且,更重要的是,告诉我为什么“F5”在 Visual Studio 中可以工作,但在外面就不行

C++ Api 定义(.h):

UPGRADE_API BOOL _stdcall WriteData(USHORT nID, BYTE dest, PBYTE pDataBuffer, USHORT nBufferSize, DWORD dwLayer=0);

//...

#define UPGRADE_API __declspec(dllimport)

我的 C# 代码:

        [DllImport("Upgrade.dll", EntryPoint = "WriteData", CallingConvention = CallingConvention.StdCall)]
        public static extern int WriteData(int id, byte dest, char[] data, int len);


//...
            var resource = "Test";
            var array = resource.ToCharArray();
            var r = WriteData(33, 0, array, array.Length);
            if (r == 0)
            {
                MessageBox.Show("Failed");
                return;
            }
            MessageBox.Show($"Ok: {resource}");

C++ api 是第三方 dll,我只有 .h 文件,因此无法直接使用 C++ 代码进行调试。

我尝试使用 x64 构建 C# 应用程序,但 c++ api 崩溃了。我构建了调试,与发布相同。

我检查了VS中的启动选项,它是空的。

我测试了很多api参数的数据类型,比如uint/ushort/short id、StringBuilder/string data、int/ushort len。有些类型是错误的,甚至VS中的“F5”也返回0。但是所有这些类型,总是会出现PInvokeStackImbalance

c# .net pinvoke
1个回答
0
投票

WriteData
的C++原型,有5个参数。其中之一有默认值,但您仍然需要传递它:具有默认值的参数始终会传递给被调用的函数,您可以在调用中省略它,但处理的方式是由编译器插入该值被设置为该参数的默认值。您不能从 dll 导入中省略它,因为这样就不会传递该参数really,导致(对于 stdcall 函数)向堆栈推送的数据少于被调用函数返回时释放的数据(stdcall 函数负责释放自己的数据)参数)。因此堆栈不平衡。

此外

PBYTE pDataBuffer
建议您应该在 C# 中传递
byte[]
,也许不需要,但该类型并不建议
WriteData
适用于 16 位字符(就像 C# 中的
char
一样)。

您尝试过的不同类型对于

id
len
参数不会产生显着差异,当它们被推送到 x86 中的堆栈时,它们都会被推送为双字。

© www.soinside.com 2019 - 2024. All rights reserved.