0

目前我正在尝试使用 DLL 导入在 C# 下使用 C++ 库。库被称为拦截。问题是我不知道如何翻译头文件的#define 条目和 typedef 声明:

https://github.com/oblitum/Interception/blob/master/include/interception.h

我尝试使用“使用”指令,但没有成功(我无法访问 void 定义)。此外,我没有理解 __declspec(dllimport) 在这个头文件中的作用。在我的 c# 项目中,我只是忽略了它?这样做好吗?

这是我想在 c# 中使用的代码(它是库的示例)

https://github.com/oblitum/Interception/blob/master/samples/hardwareid/main.cpp

编辑:

我试过的:基本进口:

[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
    void interception_set_filter(void* context, InterceptionPredicate predicate, ushort filter);

我不知道如何转换 InterceptionPredicate。根据头文件,InterceptionFilter是一个ushort,InterceptionContext是一个void指针(void*)。

4

3 回答 3

2

C++ 库应编译为 .DLL 文件。这个 .DLL 文件应该有导出的函数。您可以使用Depends工具检查从 .DLL 导出的内容。.NET 代码可以使用所谓的“平台调用”调用 C++ 导出函数。

现在,我强烈建议您深入了解本平台调用教程,它将为您提供指导。

PS:void *应该在c#中声明为IntPtr。enums应该重新声明为枚举。函数应声明为带有DllImport属性的静态外部方法。

于 2012-10-29T16:45:51.700 回答
1

首先,看起来您正在尝试实现全局键盘/鼠标挂钩..如果是这种情况,我建议您使用谷歌搜索“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*类型应该始终是IntPtrC# 中的。

此外,请务必将 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
        }
    }
}

希望这能让你走上正轨。

于 2012-10-29T17:48:39.033 回答
0

好的,我找到了隐藏在 GIT 中的示例代码。谢谢谷歌!

https://gist.github.com/1959219

它通过一个工作示例精确地从 DLL 导入中获取所有功能。

于 2012-10-30T14:43:47.057 回答