|
-
September 17th, 2007, 02:09 PM
#1
Trying to call a CLI function from native C++.
Hello again folks, I'm receiving this error:
Run-Time Check Failure #0 - 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.
...when returning from a CLI function (whose parameter is considered "out of scope" for some reason).
Code:
MyClass
{
delegate void delegateOnTerminated(int State);
delegateOnTerminated^ _TerminatedDelegate;
void _internalOnTerminatedEventHandler(int);
GCHandle _TerminatedHandle;
delegate void OnTerminatedEventHandler(System::Object^ sender, MyClass::MyClassEventArgs^ e);
event OnTerminatedEventHandler^ OnTerminated;
};
how I bind the CLI member function to the native function pointer in MyClass ctor:
MyClass::MyClass()
{
_TerminatedDelegate = gcnew delegateOnTerminated(this, &MyClass::_internalOnTerminatedEventHandler);
_TerminatedHandle = GCHandle::Alloc(_TerminatedDelegate);
System::IntPtr DelegatePtr = Marshal::GetFunctionPointerForDelegate(_TerminatedDelegate);
OnTerminatedEvent nativeDelegatePtr = static_cast<OnTerminatedEvent>(DelegatePtr.ToPointer());
_stateNotifier->TerminationEventHandlers().push_back(nativeDelegatePtr);
}
Implementation of _internalOnTerminatedEventHandler:
void MyClass::_internalOnTerminatedEventHandler(int State)
{
MyClassEventArgs e = MyClassEventArgs();
switch(State)
{
case -1:
e.TerminationReason = CompletionType::Unfinished;
break;
case 0:
e.TerminationReason = CompletionType::Success;
break;
case 1:
e.TerminationReason = CompletionType::Cancelled;
break;
case 2:
e.TerminationReason = CompletionType::Unknown;
break;
default:
e.TerminationReason = CompletionType::Unknown;
}
OnTerminated(this, %e);
}
Now native:
Code:
nativeMain.h:
class nativeMain
{
private:
std::vector<OnTerminatedEvent> OnTerminatedEventHandlers;
public:
inline void OnTerminated(int State);
};
nativeMain.cpp:
void nativeMain::OnTerminated(int State)
{
int size = static_cast<int>(OnTerminatedEventHandlers.size());
if (size > 0)
{
for (int i = 0; i < size; ++i)
{
if (OnTerminatedEventHandlers[i] != 0)
{
OnTerminatedEventHandlers[i](State);
}
}
}
}
in a separate file:
typedef void (__thiscall *OnTerminatedEvent)(int);
Okay, so when calculations complete, OnTerminated(int State) is called, passing the completion state as an int parameter. OnTerminatedEventHandlers contains a pointer which is actually a manaqed member function of the CLI wrapper. The idea is that the native code calls the CLI function, the CLI function uses the parameter to throw a managed (and exposed) event which gets handled by C# UI code. I'm having two problems:
1) The parameter passed in to the CLI function is considered "out of scope" when debugging (why?).
2) The error mentioned at the beginning of this post.
Thanks,
Geoff
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|