DLLImport:传递short类型参数

时间:2010-11-15 22:26:01

标签: c# c++ pinvoke dllimport parameter-passing

我正在尝试将短类型的参数传递给从DLL导入的C ++非托管函数。在我的C ++ DLL代码中,我有以下功能:

__declspec(dllexport)void ChangeIcon(char *executableFile, char *iconFile,
    UINT16 imageCount)
{
    // Some code, doesn't matter
}

在C#托管代码中,我使用以下代码导入此函数:

[DllImport("IconChanger.dll")]
static extern void ChangeIcon(string executableFile, string iconFile,
    ushort imageCount);

然后我称之为:

ushort imageCount = 2;
ChangeIcon("filePath", "iconPath", imageCount);

应用程序执行函数就好了;但是,弹出带有以下文字的消息:

  

托管调试助手'PInvokeStackImbalance'检测到'foo.exe'中存在问题。   附加信息:调用PInvoke函数'bar.IconChanger :: ChangeIcon'使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

如果我没有传递最后一个参数,则消息不会弹出,所以它必须是由于传递短类型。我也试过过int,会出现相同的消息。

显然,我在传递这个数字参数时做错了。如何匹配两者之间的参数?

2 个答案:

答案 0 :(得分:3)

确保调用约定匹配。如果未指定调用约定,则假定为StdCall。但是对于C / C ++,标准调用约定是Cdecl。所以要么在C ++函数上使用__stdcall

void __declspec(dllexport) __stdcall ChangeIcon(char *executableFile, char *iconFile,
    UINT16 imageCount)
{
    // Some code, doesn't matter
}

或在CallingConvention.Cdecl上指定DllImport

[DllImport("IconChanger.dll", CallingConvention = CallingConvention.Cdecl)]

作为旁注,UInt16不是CLS合规类型,因此如果您需要此合规性,可能需要Int16

答案 1 :(得分:0)

因为您在C ++函数的参数中使用char *,所以我建议您以这种方式导入函数: [DllImport(“IconChanger.dll”,CallingConvention = CallingConvention.Cdecl)] static extern void ChangeIcon([MarshalAs(UnmanagedType.LPStr)string executableFile,[MarshalAs(UnmanagedType.LPStr)string iconFile,ushort imageCount);