编组字符 *
Posted
技术标签:
【中文标题】编组字符 *【英文标题】:Marshalling char * 【发布时间】:2011-02-21 21:07:41 【问题描述】:我的 c++ dll 上有以下方法签名:
extern char *bpStringCalc(char *bpDirectory, char *issString);
我正在尝试使用以下方法从 c# 调用它:
[DllImport(@"C:\MuniAxis\Bp\BpDLL.dll", CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string bpStringCalc([MarshalAs(UnmanagedType.LPStr)] string bpDirectory,
[MarshalAs(UnmanagedType.LPStr)] string issString);
但它不断收到此异常:
'ConsoleApplication1!ConsoleApplication1.Program::bpStringCalc' 使堆栈不平衡。这是 可能是因为托管的 PInvoke 签名与非托管的不匹配 目标签名。检查 调用约定和参数 PInvoke 签名匹配目标 非托管签名。
有什么想法吗?
谢谢
【问题讨论】:
据我所知,使用StringBuilder
而不是字符串会更幸运。
确保在调用方法之前将字符串实例固定在内存中。
@BrokenGlass:考虑到参数不是问题,应该没有区别。
【参考方案1】:
尝试在导入时指定 Cdecl
调用约定或在导出时指定 __stdcall
。见this almost similar question。
【讨论】:
+1 用于类似的问题链接和(正确)在__stdcall
之前放置两个下划线,我最初搞砸了:)
这就是答案。 C++ 默认为__cdecl
,但出于某种疯狂的原因,P/Invoke 默认为__stdcall
。
@DeadMG DllImport
默认为Winapi
,根据平台选择StdCall
或Cdecl
。
@DeadMG:默认为__stdcall
,因为P/Invoke最常用的就是调用Win32函数,Win32全部使用__stdcall
。
@Billy:考虑到我在几分钟前回答了这个问题,很难不提供链接 :)【参考方案2】:
不平衡堆栈可能更多地与调用约定有关,而不是与实际参数有关。默认情况下,C++ 使用 __cdecl
调用约定。 C# 默认为 __stdcall
,因为 __stdcall
是 Win32 使用的约定。您需要在 C# 中的 import 语句中设置 calling convention,或者您需要在 C++ 二进制文件中指定 __stdcall
。
编辑:对以上内容进行了编辑,以修正__cdecl
和__stdcall
各自只有一个前导下划线的事实;)
【讨论】:
以上是关于编组字符 *的主要内容,如果未能解决你的问题,请参考以下文章