3

我正在开发指纹设备,制造商(Upek)给了我一个 c++ BSAPI.dll,所以我需要使用包装器来让它在.net 中工作。

我可以在内存中处理这一切,我可以抓取并匹配指纹。

现在我一直在尝试将数据导出到文件中,然后将其加载回内存并获取 IntPtr。

这里有一个关于如何从文件导出和导入的 c++ 示例。但我不知道怎么读。

感谢任何帮助谢谢大家


这就是我所拥有的并且效果很好: 在此处输入图像描述

现在我需要两件事 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

IntPtr只是一个 .NET 类型void*。它本身并不意味着任何意义。您需要知道内存包含什么,并确保 .NET 和 C 端使用相同的内存布局。

您可以通过两种主要方式在托管代码和非托管代码之间进行交互。

一种是 C++/CLI (IJW)。如果您固定托管对象或数组,则可以将其传递给非托管函数。但是,对于复杂类型,您可能会遇到麻烦,因为 .NET 的内存布局不一定与您的 C 库所期望的相同。检查pin_ptr以获取更多信息。

第二种流行的方法是使用p/invoke,您可以将 C# struct(C++/CLI value struct) 编组为 C struct,甚至是它们的数组。您有一种方法可以指定内存布局,是否string应该被编组为 MBCS 或 UTF-16,结构应该如何对齐等等。以这种方式直接从 C# 调用 C 函数很容易。

于 2011-05-03T21:07:29.350 回答
3

这是我很久以前获得的用于与BioAPI交互的 C# 代码(我认为是从 BIOAPI 示例代码中获得的)。DoMarshall 方法返回一个 IntPtr 指向已分配的足够大的内存以容纳数组。

我没有使用托管 C++,所以我不确定需要进行哪些更改,但也许它会为您指明正确的方向。当时我正在与 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 回答