Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Указатель как тип возвращаемого значения функции


Автор: CYBERDREAM 15.11.2007, 18:54
Приветсвую всех.
Столкнулся со следующей проблемой. Переписываю код с плюсов на шарп, и у одной функции возвращаемый параметр является указателем на структуру, как быть в случае шарпа?

Код

         {
              ....
              READER *myReaderHandle = MAPI_Connect( readerHost, NULL, &connectResult ); //собственно сама виновница
              ...
         }
         struct READER; 

вот что получил на шарпе:
Код

    public class PInvokeClient
    {
        [DllImport("libMach1.dll")]
        public static extern READER MAPI_Connect(string host,int k,ref MAPI_CONNECT_ERROR sl);//вот собственно как здесь задать указатель на структуру?

        public static int Main(string[] args)
        {
            MAPI_CONNECT_ERROR connectResult=new MAPI_CONNECT_ERROR();
            //Connect
            string _readerHost = "192.168.127.22";

            READER _reader=new READER();// = MAPI_Connect(_readerHost,0,ref connectResult);
            IntPtr rea=Marshal.AllocHGlobal(Marshal.SizeOf(_reader)); 
            Marshal.StructureToPtr(_reader,rea,false);                               //Ссылка на стркутру
            rea = MAPI_Connect(_readerHost,0,ref connectResult);           // здесь обишка несовпадение возвращаемых типов.
            ....
        }
        public struct READER{};

как правильно объявить функцию?

Автор: 0000 15.11.2007, 19:13
так..сначала написал неподумавши - не скомпилит =)

надо приписать атрибут [MarshalAs(UnmanagedType.LPStruct)]
щас...

вот описание если что:
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype.aspx

Добавлено через 9 минут и 3 секунды
попробуй так:

Код

[DllImport("libMach1.dll")] 
[return: MarshalAs(UnmanagedType.LPStruct)]
public static extern READER MAPI_Connect(string host,int k,ref MAPI_CONNECT_ERROR sl);

Автор: CYBERDREAM 15.11.2007, 22:15
Ошибочка в итоге абсолютно та же, хотя по идее должно именно так работать,  smile 

Автор: 1stain 15.11.2007, 23:36
CYBERDREAM, у тебя в примере написано  public struct READER{};
в коде так же?

Автор: CYBERDREAM 16.11.2007, 09:12
да, а в чем загвоздка то? в том, что стркутура пустая? на плюсах она так и представляется как и описано выше? или нужно иначе?

Автор: 1stain 16.11.2007, 09:25
в структуре надо прописать ее поля. Например, COLORREF для того, чтобы принять его из unmanaged объявляется так
Код

[StructLayout(LayoutKind.Sequential)]
struct COLORREF {
   public byte R;
   public byte G;
   public byte B;
}

// Alternate
[StructLayout(LayoutKind.Sequential)]
public struct COLORREF
{
   public uint ColorDWORD;

   public COLORREF(System.Drawing.Color color)
   {
      ColorDWORD = (uint) color.R + (((uint) color.G) << 8) + (((uint) color.B) << 16);
   }

   public System.Drawing.Color GetColor()
   {
      return System.Drawing.Color.FromArgb((int) (0x000000FFU & ColorDWORD),
     (int) (0x0000FF00U & ColorDWORD) >> 8, (int) (0x00FF0000U & ColorDWORD) >> 16);
   }

   public void SetColor(System.Drawing.Color color)
   {
      ColorDWORD = (uint) color.R + (((uint) color.G) << 8) + (((uint) color.B) << 16);
   }
}


в принципе, методы можно не объявлять (первый вариант). Достаточно объявить в структуре все поля в таком же порядке и соответствующих типов, как в неуправляемом варианте (если структура содержит массивы там немного больше геморроя с их объявлением). И не забыть атрибут [StructLayout(LayoutKind.Sequential)]

можешь посмотреть здесь много примеров взаимодействия с unmanaged кодом : http://pinvoke.net/index.aspx
кстате COLORREF именно оттуда

Автор: CYBERDREAM 16.11.2007, 09:29
Ок, если должны быть поля (я и сам такого мнения), то почему на плюсах их нету
Код

struct READER;


или я что-то не улавливаю

Автор: 1stain 16.11.2007, 10:34
честно сказать, я вообще в плюсах (т.е. в mapi.h) не нашел определения структуры READER. Насколько я понял, это какая-то сторонняя библиотека? Если есть исходники, то ты смотрел заголовочные файлы?

Автор: CYBERDREAM 16.11.2007, 10:42
вот что в mapi_control.h находится:

Код

#ifndef _MAPI_CONTROL_H_
#define _MAPI_CONTROL_H_

/* Declaration of the reader handle. */
struct READER;         

enum MAPI_ERROR
{
    /** The packet has an invalid start byte. */
    MAPI_ERROR_MSG_STARTBYTE,
    /** The packet has a malformed header. */
    MAPI_ERROR_MSG_HEADER,
    .....
};

............
DLLEXPORT unsigned int MAPI_GetLibraryVersion (void);
........
#endif


по документации собственно вот:
This file “mapi_control.h” defines a generic handle type for established connections between the application and the reader as follows.
Код

/* Declaration of the reader handle. */
struct READER;

Автор: CYBERDREAM 16.11.2007, 13:31
Работающий вариант:
Код

    public class PInvokeClient
    {
        [DllImport("libMach1.dll")] 
        public static extern IntPtr MAPI_Connect(string host,int k,ref MAPI_CONNECT_ERROR sl);

        public static int Main(string[] args)
        {
            IntPtr ptr=MAPI_Connect(_readerHost,0,ref connectResult);
            if(ptr==IntPtr.Zero)
            {
                Console.WriteLine("Failed to connect  {0}",_readerHost);
                ....
            }
            else
            {
                READER r=(READER)Marshal.PtrToStructure(ptr, typeof(READER));
                Marshal.DestroyStructure(ptr,typeof(READER));
            }
        }
    }

Спасибо большое 0000 и 1stain за помощь!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)