首先,看起来您正在尝试实现全局键盘/鼠标挂钩..如果是这种情况,我建议您使用谷歌搜索“C# 低级键盘和鼠标挂钩”。
现在对于您的问题,首先是__declspec(dllimport)
问题:如果您实际上是在 C++ 应用程序中使用标头,那是 C# 的 C++ 等价物DllImport
.. 所以实际上您并没有忽略它,而是实现了它。在 C++ 中,它只是告诉链接器声明的函数将从特定的 DLL 导入,而不是本地函数(与 C#DllImport
指令的作用非常相似)
接下来是函数指针问题(InterceptionPredicate)。在标题中,它被定义为:
typedef int (*InterceptionPredicate)(InterceptionDevice device);
并且InterceptionDevice
只是一个'int'。所以 InterceptionPredicate 只是一个函数指针类型(或 C# 中的 Delegate),所以 InterceptionPredicate 的委托定义如下所示:
// [UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int InterceptionPredicate (int device);
关于 UnmanagedFunctionPointer 调用约定描述符的注释:如果您知道导出的函数可能使用哪种调用约定(stdcall、fastcall、cdecl),您可以在此处指定,以便 .NET 封送拆收器知道如何在托管/非托管代码,但如果您不知道它或通常未指定它,您可以将其关闭。
此外,正如其他人所提到的,除非您在 C# 属性中指定了“不安全”标志,否则void*
类型应该始终是IntPtr
C# 中的。
此外,请务必将 C# 代码中的 dll 函数标记为public static extern
,请参见下面的示例。
因此,为了举例说明您指定的函数,可以执行以下操作:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace InterceptorTest
{
public class Interceptor : IDisposable
{
#region DllImports
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr interception_create_context();
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void interception_destroy_context(IntPtr context);
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void interception_set_filter(IntPtr context, InterceptionPredicate predicate, ushort filter);
// The function pointer type as defined in interception.h that needs to be defined as a delegate here
public delegate int InterceptionPredicate(int device);
#endregion
#region private members
private InterceptionPredicate m_PredicateDelegate { get; set; }
private IntPtr m_Context { get; set; }
#endregion
#region methods
public Interceptor(ushort filter)
{
// be sure to initialize the context
this.m_PredicateDelegate = new InterceptionPredicate(this.DoSomethingWithInterceptionPredicate);
this.m_Context = interception_create_context();
interception_set_filter(this.m_Context, this.m_PredicateDelegate, filter);
}
private void Cleanup()
{
interception_destroy_context(this.m_Context);
// the next line is not really needed but since we are dealing with
// managed to unmanaged code it's typically best to set to 0
this.m_Context = IntPtr.Zero;
}
public void Dispose()
{
this.Cleanup();
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing) { this.Cleanup(); }
}
public int DoSomethingWithInterceptionPredicate(int device)
{
// this function is something you would define that would do something with
// the device code (or whatever other paramaters your 'DllImport' function might have
// and return whatever interception_set_filter is expecting
return device;
}
#endregion
}
static class Program
{
[STAThread]
private static void Main(string[] argv)
{
Interceptor icp = new Interceptor(10);
// do something with the Interceptor object
}
}
}
希望这能让你走上正轨。