我有一个非托管C ++函数驻留在我从C#应用程序调用的Dll中。这是函数的签名:
GetCrashMeasurement(LPCTSTR channelName, LPCTSTR properties, LPCTSTR * Values, HANDLE error)
其中channelName
和properties
是输入参数[in];并且Values
是输出参数[out]。
我也在使用C#应用程序中的Platform调用,如下所示:
[DllImport("DrvCrashHAL.dll", EntryPoint = "coCRAL_GetCrashMeasurements")]
public static unsafe extern CoStatus GetCrashMeasurements(string sChannel, string sMeasurements, ref string sValues, IntPtr hError);
从我的C#应用程序中,我按以下方式调用该函数:
string Text = "";
intptr herror = intptr.zero;
GetCrashMeasurements("channelname","",ref Text,herror);
但是我的程序完全停在此行而没有抛出任何异常,我在输出窗口中看到的只是以下消息:
Critical error detected c0000374
Critical error detected c0000374
The program '[4964] ProjectX.exe: Managed' has exited with code 0 (0x0).
The program '[4964] ProjectX.exe: Native' has exited with code 0 (0x0).
我的猜测是,问题在于LPCTSTR
的编组类型。
有谁能告诉我我做错了什么或者指出了正确的方向?
提前致谢。
答案 0 :(得分:1)
据我所知,你所提供的参数1,2和4应该很好。问题可能是参数3。
错误c0000374是堆损坏。这适合。
尝试解决问题的问题是要知道第3个参数的作用。它被声明为一种char**
,并且作为[out]参数,我希望它输出为char*
。换句话说,我希望函数实际输出一个指针,而不是一个字符串,期望调用者将接收该指针并从中复制一个(以null结尾的)字符串。
您可以通过将入口点重新定义为int *或int **并传入intptr来调查此类调用。这样你应该(a)修复崩溃和(b)看到输出值(作为int或指针)。您可能必须为此进行自己的编组。给定指向COM BSTR的指针,您可以轻松检索所需的值。
但是,根据我对Interop规范的解读,这应该可以正确使用out string sValues
而不是ref
的声明。调用函数时会发生堆损坏,而不是在它返回时发生。
如果技术性很强,这很有用:http://msdn.microsoft.com/en-us/magazine/cc164193.aspx。
我建议你先尝试一下。如果没有,可以尝试调试路由以查看您获得的指针。
答案 1 :(得分:0)
正如@jester注意到LPCTSTR* Values
听起来更像是一个字符串数组。您可以尝试将第三个参数更改为字符串数组吗?
public static unsafe extern CoStatus GetCrashMeasurements(string sChannel, string sMeasurements, string[] sValues, IntPtr hError);
并按如下方式调用
GetCrashMeasurements("channelname","",new[] { Text },herror);
您也可以在MarshalAs
上指定sValues
。
public static unsafe extern CoStatus GetCrashMeasurements(string sChannel,
string sMeasurements,
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPTStr)]
string[] sValues,
IntPtr hError);