我正在使用指纹设备,制造商(Upek)给了我一个c ++ BSAPI.dll,所以我需要使用包装器才能在.net中使用它。
我可以从内存中使用它,我可以抓住并匹配指纹。
现在我不得不尝试将数据输出到文件中,然后将其重新加载到内存中并获取IntPtr。
Here有关于如何从文件导出和导入的c ++示例。但我不知道怎么读。
感谢所有帮助
这就是我的所作所为并且效果很好:
现在我需要两件事 1.将bufBIR保存到数据库中。 2.获取我保存的数据并将其传递给abs_verify。
如何做到这一点?
答案 0 :(得分:4)
我不知道问题的主体意味着什么,但要回答标题:
如何从对象获取IntPtr?
故意这需要一点点工作,这是有充分理由的。垃圾收集器通常可以在内存中重新定位对象,因此可以通过“固定”它来完成。为此,您必须使用GCHandle'固定'创建GCHandleType,然后拨打GCHandle.AddrOfPinnedObject。如果没有固定,这将抛出异常。
另外,您应该注意GCHandle.ToIntPtr返回句柄的值而不是对象的地址。这基本上用于具有单个整数值,可以在重构GCHandle之前轻松传递。
答案 1 :(得分:3)
这是我很久以前与BioAPI接口的C#代码(我想从BIOAPI示例代码中得到)。 DoMarshall方法返回一个IntPtr,指向分配的内存足够大以容纳数组。
我没有使用Managed 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 ); }
}
}
答案 2 :(得分:2)
IntPtr
只是void*
的.NET类型。它本身并不意味着任何意义。您需要知道内存包含的内容,并确保.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函数很容易。