我有一个C dll,我正在包装,以便我可以从C#调用它。一个函数使用事件在状态发生变化时通知您,并且计算出来处理它需要进行一些挖掘。它似乎工作正常,但我很好奇是否有人比我更有经验,可以提供任何建议。
该函数在dll的.h文件中定义为:
int NotifyStateChange(OVERLAPPED *overlapped);
typedef int (*NOTIFY_STATE_CHANGE_PROC)(OVERLAPPED *);
调用它的示例C代码:
OVERLAPPED overlapped;
overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
fns.NotifyStateChange(&overlapped);
WaitForSingleObject(overlapped.hEvent, INFINITE);
// ...query for the new state or whatever...
这就是我在C#中接近它的方式:
[DllImport("myfuncs.dll")]
unsafe public static extern int NotifyStateChange(NativeOverlapped* lpOverlapped);
static private ManualResetEvent m_stateChangeEvent = new ManualResetEvent(false);
public static DeviceState WaitForStateChange()
{
unsafe
{
Overlapped overlapped = new Overlapped(0, 0,
m_stateChangeEvent.SafeWaitHandle.DangerousGetHandle(), null);
IOCompletionCallback callback = StateChangeCallback;
byte[] userData = new byte[100];
NativeOverlapped* nativeOverlapped = overlapped.Pack(callback, userData);
NotifyStateChange(nativeOverlapped);
m_stateChangeEvent.WaitOne();
Overlapped.Unpack(nativeOverlapped);
Overlapped.Free(nativeOverlapped);
}
return GetCurrentState();
}
[ComVisibleAttribute(true)]
unsafe static public void StateChangeCallback (
uint errorCode,
uint bytesTransferred,
NativeOverlapped* overlapped)
{
m_stateChangeEvent.Set();
}
我不清楚的一件事是需要userData。 NotifyStateChange只会触发一个事件,它不会返回任何数据。将null userData传递给Pack()似乎工作正常,但我担心有些东西可能会在我不知道的封面下发生。
如果有更合适的方法,我很感激任何建议。
埃里克
答案 0 :(得分:4)
您已经阻止事件句柄,不需要使用Overlapped类和回调。您所要做的就是将NativeOverlapped.EventHandle成员设置为DangerousGetHandle()返回值。 DLL将设置事件。
此外,将NotifyStateChange的参数声明为ref而不是指针,使您不必使用unsafe关键字。
答案 1 :(得分:3)
啊是的 - 这正是我向stackoverflow提出难题的原因。现在似乎很明显。这是简化的代码......
[DllImport("myfuncs.dll")]
public static extern int NotifyStateChange(ref NativeOverlapped lpOverlapped);
public static DeviceState WaitForStateChange()
{
ManualResetEvent stateChangeEvent = new ManualResetEvent(false);
NativeOverlapped nativeOverlapped = new NativeOverlapped();
nativeOverlapped.EventHandle =
stateChangeEvent.SafeWaitHandle.DangerousGetHandle();
NotifyStateChange(ref nativeOverlapped);
stateChangeEvent.WaitOne();
return GetCurrentState();
}
谢谢!
埃里克
答案 2 :(得分:1)
似乎DLL设计者决定使用OVERLOAPPED结构,无论出于何种原因,他们只需使用简单的HANDLE就可以发出事件信号。显然他们不会查看OVERLAPPED结构中的其他字段,因为DLL似乎没有使用它来使用重叠数据(指针和偏移量)执行任何类型的I / O操作。因此,在不了解所述DLL的情况下,看起来您的使用是正确的,并且您可以传递nil表示数据,0表示偏移量。
但请记住,这只是猜测。如果可能,请联系DLL作者,如果他们忽略指针和偏移的假设是正确的,请询问澄清。
作为旁注,如果你要收到一个回调,我不会阻止等待状态变化的线程。只需使用回调来处理事件(状态改变),系统将更好地扩展。