3

私は指紋デバイスに取り組んでいます。製造元(Upek)からc ++ BSAPI.dllが提供されたため、これを.netで機能させるにはラッパーを使用する必要があります。

私はメモリ内からすべてを処理することができ、指紋をつかんで一致させることができました。

今、私はデータをファイルに取り出してからそれをメモリにロードしてIntPtrを取得しようとして立ち往生しています。

ここに、ファイルからエクスポートおよびインポートする方法に関するc++サンプルがあります。でも読み方がわかりません。

助けていただければ幸いですありがとうございました


これは私が持っているものであり、うまく機能します: ここに画像の説明を入力してください

今私は2つのものが必要です1.そのbufBIRをデータベースに保存します。2.保存したデータを取得し、abs_verifyに渡します。

これはどのように行うことができますか?

4

3 に答える 3

4

質問の本文が何を意味するのかわかりませんが、タイトルに答えるには:

オブジェクトから IntPtr を取得するにはどうすればよいですか?

これは、正当な理由により、意図的に少し作業が必要になるように作成されています。ガベージ コレクターは、多くの場合、メモリ内のオブジェクトを再配置できるため、それを「固定」することによってのみ実行できます。これを行うには、 GCHandleType 'Pinned'でGCHandleを作成する必要があります。その後、 GCHandle.AddrOfPinnedObjectを呼び出すことができます。固定されていない場合、例外がスローされます。

また、 GCHandle.ToIntPtrは、オブジェクトのアドレスではなく、ハンドルの値を返すことに注意してください。これは基本的に、GCHandle を再構築する前に簡単に渡すことができる単一の整数値を持つために使用されます。

于 2012-01-17T10:49:58.890 に答える
3

これは、 BioAPIとインターフェイスするためにずっと前に取得したC#コード(BIOAPIサンプルコードからだと思います)です。DoMarshallメソッドは、配列を保持するのに十分な大きさの割り当てられたメモリを指すIntPtrを返します。

私はManagedC++を使用したことがないので、どのような変更が必要かわかりませんが、正しい方向を示す可能性があります。当時はUPEKで働いていました。これがお役に立てば幸いです...

    [Serializable]
[StructLayout(LayoutKind.Sequential)]
public class BioAPI_DATA 
{
    public uint Length = 0;
    public byte[] Data = null;
    public BioAPI_DATA() {}
    public BioAPI_DATA(uint length, byte[] data) { Length = length; Data = data; }

    public IntPtr DoMarshal(ref int size)
    {
        IntPtr ptr;
        IntPtr ptrData = IntPtr.Zero;
        int ofs = 0;

        size = Marshal.SizeOf(Type.GetType("System.Int32")) + 
               Marshal.SizeOf(Type.GetType("System.IntPtr"));

        ptr = Marshal.AllocCoTaskMem( size );
        Marshal.WriteInt32(ptr, ofs, (int) Length);
        ofs += Marshal.SizeOf(Type.GetType("System.Int32"));
        if (Data != null) 
        {
            ptrData = Marshal.AllocCoTaskMem( Data.Length );
            Marshal.Copy(Data, 0, ptrData, Data.Length);
        }
        Marshal.WriteIntPtr(ptr, ofs, ptrData);
        return ptr;
    }

    public void DoUnmarshal(IntPtr ptr, ref int size, bool fDeleteOld)
    {
        int ofs = 0;
        size = Marshal.SizeOf(Type.GetType("System.Int32")) + 
               Marshal.SizeOf(Type.GetType("System.IntPtr"));
        Length =  (uint) Marshal.ReadInt32( ptr, ofs );
        ofs += Marshal.SizeOf(Type.GetType("System.Int32"));

        if (Length == 0) 
        {
            if (Data != null) Data = null;
            return;
        }

        IntPtr ptr2 = Marshal.ReadIntPtr(ptr, ofs);

        if (Data == null || Data.Length != Length) Data = new byte[Length];
        Marshal.Copy(ptr2, Data, 0, (int) Length);
        if (fDeleteOld)  { if (ptr != IntPtr.Zero) Marshal.FreeCoTaskMem( ptr ); }
    }
}
于 2011-05-03T21:24:17.467 に答える
3

IntPtrは .NET の単なる .NET タイプですvoid*。それ自体に意味があるわけではありません。メモリの内容を把握し、.NET 側と C 側が同じメモリ レイアウトを使用していることを確認する必要があります。

マネージ コードとアンマネージ コードの間のインターフェイスには、主に 2 つの方法があります。

1 つは C++/CLI (IJW) です。マネージ オブジェクトまたは配列を固定すると、アンマネージ関数に渡すことができます。ただし、.NET のメモリ レイアウトは C ライブラリが期待するものと必ずしも同じではないため、複雑な型を使用すると問題が発生する可能性があります。詳細については、 pin_ptrを確認してください。

2 番目に一般的な方法は、p/invokestructを使用する方法です。この方法では、C# (C++/CLI value struct) を Cstructに、またはそれらの配列にマーシャリングできます。stringMBCS または UTF-16 としてマーシャリングする必要があるかどうか、構造をどのように配置する必要があるかなど、メモリ レイアウトを指定する方法があります。このように、C# から直接 C 関数を簡単に呼び出すことができます。

于 2011-05-03T21:07:29.350 に答える