我正在使用C语言在VB.Net和DLL B中编写Add-inn Application A. 应用程序传递回调方法到dll B. 当某些事件发生时,dll从A调用回调。 整个在我的电脑上工作正常但是当我把它移到Notebook时我得到一个错误:
运行时检查失败#0 - ESP的值未在函数调用中正确保存。这通常是调用使用一个调用约定声明的函数和使用不同调用约定声明的函数指针的结果。
这是C代码的一部分:
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3){
switch (dwMessage)
{
case LINE_CALLSTATE:
switch (dwParam1)
{
case LINECALLSTATE_OFFERING:
if(dwInstance!=NULL)
{
try
{
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
}
catch(...)
{
MessageBox (NULL, L"( (OFFICE_PTR)dwInstance )(&sCallNr)",L"ERROR",MB_OK);
}
}
break;
};
break;
}
}
其中dwInstance是应用程序的地址A回调方法
这是VB.Net代码的一部分:
Public Class TapiPlugin
Public Delegate Sub P_Fun()
Private Declare Function startSpy _
Lib "TAPIClient.dll" _
(ByVal pFun As P_Fun) As IntPtr
Public Shared Sub simpleTest()
MsgBox("Plugin sub simpleTest")
End Sub
Public Sub onStart()
Dim pBSTR As IntPtr
pBSTR = startSpy(AddressOf simpleTest)
MsgBox(Marshal.PtrToStringAuto(pBSTR))
Marshal.FreeBSTR(pBSTR)
End Sub
End Class
当我尝试调用'vbFunc()'时出现错误。我将不胜感激任何帮助。 :D
答案 0 :(得分:1)
如果调用约定是cdecl
,那么您需要像这样声明您的委托:
<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Sub P_Fun()
您只能在.NET 2.0及之后执行此操作,因为之前未引入该属性(并且之前没有更改互操作层以确认它)。
如果调用约定确实是stdcall
,则委托可以保持原样。你说它是stdcall
,但我有疑问,因为异常明确告诉你调用约定可能不匹配。
答案 1 :(得分:0)
两台计算机的指针大小可能不同吗?也许一个是64位机器而另一个只有32位?
typedef void (__cdecl * OFFICE_PTR)();
void TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
...){
...
OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
vbFunc( );//Critical moment
DWORD类型对于传递指针类型并不真正有效。您应该使用INT_PTR。
答案 2 :(得分:0)
我认为这不是检查它的理由我将回调作为OFFICE_PTR类型的全局指针传递,我得到相同的结果。在PC上,它可以在Notebook上崩溃:(
我必须为我写的一个错误道歉,即def看起来像:
typedef void (__cdecl * OFFICE_PTR)();
但实际上看起来像是
typedef void (__stdcall * OFFICE_PTR)();