Как я могу получить указатель IntPtr от объекта - PullRequest
2 голосов
/ 04 мая 2011

Я работаю на устройстве с отпечатками пальцев, производитель (Upek) дал мне c ++ BSAPI.dll, поэтому мне нужно использовать обертки, чтобы заставить его работать в .net.

Я могу работать со всем этим из памяти, я могу захватывать и сопоставлять отпечатки пальцев.

Теперь я застрял, пытаясь вывести данные в файл, а затем загрузить их обратно в память и получить IntPtr.

Здесь приведен пример c ++ для экспорта и импорта из файла. но я не знаю, как это читать.

Любая помощь приветствуется Спасибо всем


Это то, что у меня есть и прекрасно работает: enter image description here

Теперь мне нужны две вещи 1. Возьмите этот bufBIR и сохраните его в базе данных. 2. Возьмите данные, которые я сохранил, и передайте их в abs_verify.

Как это можно сделать?

Ответы [ 3 ]

4 голосов
/ 17 января 2012

Я не знаю, что означает основная часть вопроса, но ответить на заголовок:

Как я могу получить IntPtr от объекта?

Этонамеренно сделано, чтобы потребовать немного работы, и для этого есть все основанияСборщик мусора может часто перемещать объекты в памяти, что можно сделать только путем «закрепления».Для этого вы должны создать GCHandle с GCHandleType 'Прикреплено', а затем вы можете вызвать GCHandle.AddrOfPinnedObject .Это вызовет исключение, если оно не закреплено.

Также следует отметить, что GCHandle.ToIntPtr возвращает значение дескриптора, а не адрес объекта.Это в основном используется, чтобы иметь единственное целое значение, которое можно легко обойти перед реконструкцией GCHandle.

3 голосов
/ 04 мая 2011

Вот код C #, который я получил (я думаю из примера кода BIOAPI) давным-давно для взаимодействия с BioAPI . Метод DoMarshall возвращает IntPtr, указывающий на выделенную память, достаточно большую для хранения массива.

Я не работал с Managed C ++, поэтому я не уверен, какие изменения необходимы, но, возможно, это укажет вам правильное направление. Я работал с УПЭК в то время. Надеюсь, это поможет ...

    [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 голосов
/ 04 мая 2011

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 #.

...