0

現在、DLLインポートを使用してC#でC++ライブラリを使用しようとしています。ライブラリはインターセプトと呼ばれます。問題は、ヘッダーファイルの#defineエントリとtypedef宣言を変換する方法がわからないことです。

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

「using」ディレクティブを使用しようとしましたが、成功しませんでした(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関数は、属性でマークされた静的externメソッドとして宣言する必要があります。

于 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#のデリゲート)であるため、InterceptionPredicateのデリゲート定義は次のようになります。

// [UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int InterceptionPredicate (int device);

UnmanagedFunctionPointer呼び出し規約記述子に関する注意:エクスポートされた関数が使用している可能性のある呼び出し規約(stdcall、fastcall、cdecl)の種類がわかっている場合は、ここで指定して、.NETマーシャラーがデータをマネージド/アンマネージドコードですが、それがわからない場合や通常は指定されていない場合は、そのままにしておくことができます。

また、他の人が言及しているように、C#プロパティで「unsafe」フラグが指定されていない限り、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 に答える