1

我正在将单声道 2.10.8 嵌入到我的应用程序中,并且在注册时遇到了一些功能问题mono_add_internal_call

假设我有托管方法:

internal delegate void Win32ServiceHandler(long statusCode);

internal static class Win32Service
{
  [MethodImpl(MethodImplOptions.InternalCall)]
  public static extern void Test(Win32ServiceHandler handler);
}

这是非托管定义:

void icall_TestDelegateCallback(MonoDelegate *ftn) {
  LPHANDLER_FUNCTION f = (LPHANDLER_FUNCTION)mono_delegate_to_ftnptr(ftn);
  f(SERVICE_CONTROL_STOP);
}

和一些代码来测试:

protected virtual void ServiceHandler(Win32ServiceControl statusCode)
{   
  Console.WriteLine("here");
}

public void MakeTest()
{
  Console.WriteLine("before");
  Win32Service.Test(this.ServiceHandlerInternal);
  Console.WriteLine("after");
}

我从控制台应用程序运行它,当我调用 MakeTest() 时,输出是:

before
here

并且应用程序永远不会返回。

实际上这是一个简化的例子。在实际程序中,我需要将函数指针作为回调传递给RegisterServiceCtrlHandler诸如mono_runtime_invoke(顺便说一句工作正常)之类的东西不是我需要的。

问题是调用从 MonoDelegate 获得的函数指针的正确方法是什么?还是将其作为回调传递的任何其他正确方法?

我的平台是 Windows 7 x64

升级版:

有趣的发现。一旦我将代码更改为:

internal static class Win32Service
{
  [MethodImpl(MethodImplOptions.InternalCall)]
  public static extern void Test(Action handler);
}

typedef VOID (*TESTFTN)();

void icall_TestDelegateCallback(MonoDelegate *ftn) {
  TESTFTN f = (TESTFTN)mono_delegate_to_ftnptr(ftn);
  f();
}

和:

public void MakeTest()
{
  Console.WriteLine("before");
  Win32Service.Test(() => Console.WriteLine("here"));
  Console.WriteLine("after");
}

一切都很好。所以问题在于将 long 编组为 DWORD?在这如何解决?

4

1 回答 1

0

DWORD 是 32 位整数类型,而 C# 中的 long 是 64 位类型。

于 2012-05-15T08:54:44.083 回答