//////////////////////////////////////////////////////////////////////
질문자: 누군가 DLL 호출중 ESP 오류가 난다고 했나보다...
//////////////////////////////////////////////////////////////////////
Hello.
I'm trying to wrap a C++ dll using C#. I don't have access to the source used to create the C++ dll so I cannot alter the header files to declare the C++ callback with __stdcall. All I have is the API information.
Trouble arises when I try to wrap a function that has a callback. I get the following error:
"The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention"
This is the prototype of the C++ callback function:
{
My C# prototype is:
The arguments match (sort of, with the exception of the const). So maybe it's a calling convention problem?
Here's more of the code:
// QS_RESULT, QS_RequesterType are a enum
// QS_DeviceAddress is a struct
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct QS_MSG
{
public UInt32 Type; /* Which message is being sent to the UserCallback */
public QS_RESULT CompletionCode; /* Result of request */
public UInt32 nContextID; /* Context that caused this request */
public QS_RequesterType eRequesterType; /* Context that caused this request */
public QS_DeviceAddress DevAddr; /* The device address */
public IntPtr hSessionID;
public object hHandle;
public object MoreInfo;
}
// QS_ApplicationType is an enum
[DllImport("ViconNet.dll")]
private static QS_CALLBACK cb = new QS_CALLBACK(callbackConductor);
private static IntPtr sessionConductor;
// function which is calling the C++ DLL
private void callingFunction( )
{
byte [] ip = getIP( );
ip, cb, 0)
public static UInt32 callbackConductor(ref QS_MSG pMsg)
{
The error occurs when returning from the callback. Before the return, I inserted a breakpoint to inspect pMsg. It seems to have all the correct information. If I change the prototype of the callback to have no parameters, there is no error. How can I resolve this problem without changing the C++ code? Thanks for any feedback.
-Neal
QS_SessionHandle QS_Initialize (QS_ApplicationType eApplType,
const unsigned char ipMe[],
QS_CALLBACK pUserCallback,
unsigned long nContextID);
//////////////////////////////////////////////////////////////////////
별다섯개 답글~: 함수 호출 방식을 바꾸는 방법~~
//////////////////////////////////////////////////////////////////////
Hi Neal,
Like you may guessed, the problem is that the function pointer that the unmanaged function accepts should respect the C calling convention but the delegate instance you pass to it does not (it respects the standard calling convention (__stdcall).
If you’re using .net 2.0, you can use UnmanagedFunctionPointer Attribute to Control the marshaling behavior of a delegate signature passed as an unmanaged function pointer to or from unmanaged code. Check out the following example:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate UInt32 QS_CALLBACK(ref QS_MSG pMsg);
If you’re using .net 1.1 then you have to check out the solution here: Using C calling convention callback functions in C# and VB - the easy way.
Hope this helps!
Thanks!