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


Автор: bitwise 21.4.2008, 08:55
Всем привет!

Я пишу обертку на C# для С-библиотечки. Так вот, у меня есть структуры:
Код

struct params
{
    char*   info;
    params* next;
};

struct device
{
    unsigned int flags;
    char*        name;
    char*        description;
    params*      p_params;
    device*      next;
};



И есть пара функций:
Код

int get_device_list( device* dev );
void free_device_list( device* dev );


Так вот, что делаю я:
Код


[StructLayout(LayoutKind.Sequential)]
public class device
{
   [MarshalAs(UnmanagedType(UnmanagedType.U4)
   uint flags;

   [MarshalAs(UnmanagedType(UnmanagedType.LPStr)
   string name;

   [MarshalAs(UnmanagedType(UnmanagedType.LPStr)
   string description;

   IntPtr p_params;
   IntPtr next;

   public device() 
   {
      name        = new string( '\0', 100 );
      description = new string( '\0', 100 );
      flsgs       = 0;
      p_params    = IntPtr.Zero;
      next        = IntPtr.Zero;
   }

}

// Экспортирую ф-ции из DLL
   [Dllimport("api.dll")]
   static extern int get_device_list( IntPtr device_ptr );

   [Dllimport("api.dll")]
   static extern int free_device_list( IntPtr device_ptr );


public static void main()
{
    device dev;
    IntPtr device_ptr = Marshal.AllocHGlobal( Sizeof( typeof( device ) ) );
    Marshal.StructureToPtr( dev, device_ptr, false ) );

    int result = get_device_list( device_ptr ); // Здесь все хорошо
    
    free_device_list( device_ptr ); // А здесь бросается исключение "Попытка чтения или записи в защищенную память. Возможно память повреждена"

    Marshal.FreeHGlobal( device_ptr );
}




Так вот я не понимаю, почему отрабатывает вызов первой функции и не отрабатывает вызов второй. Помогите пожалуйста, че-то я никак не соображу где ошибся. Спасибо.

Автор: mullih 21.4.2008, 10:29
Может
void free_device_list( device* dev );
   [Dllimport("api.dll")]
   static extern int free_device_list( IntPtr device_ptr );

Автор: bitwise 21.4.2008, 10:40
Прошу прщения, я очепятался...

int get_device_list( device* dev );
void free_device_list( device* dev );

и соответственно...

[Dllimport("api.dll")]
static extern int get_device_list( IntPtr device_ptr );

[Dllimport("api.dll")]
static extern void free_device_list( IntPtr device_ptr );

Автор: mullih 21.4.2008, 10:47
а можно код функций
int get_device_list( device* dev );
void free_device_list( device* dev );

Автор: bitwise 21.4.2008, 11:04
К сожалению кода нет... Это сторонняя DLL smile 
Может я структуру неправильно отмаршалил?

Автор: mullih 21.4.2008, 11:27
С описанием не помогу так как точно не уверен но попробуй в шарпе 
struct params
{
    char*   info;
    params* next;
};

описать и p_params сделать объетом этой структуры

Автор: bitwise 21.4.2008, 14:26
Я обязательно попробую и отпишусь о результате...

Автор: mr.DUDA 24.4.2008, 10:17
Цитата(bitwise @  21.4.2008,  11:04 Найти цитируемый пост)
Может я структуру неправильно отмаршалил?

Вместо IntPtr можно саму структуру по ref передать:
Код
   [Dllimport("api.dll")]
   static extern int get_device_list(ref device device_ptr);

   [Dllimport("api.dll")]
   static extern void free_device_list(ref device device_ptr);


public static void main()
{
    device dev = new device();

    int result = get_device_list(ref dev);
    
    free_device_list(ref dev);
}


Автор: bitwise 24.4.2008, 10:59
В общем бага оказалась надуманной, всем спасибо за брейнсторм.

Оказывается ф-ция выглядит так: int get_device_list( device** dev ); вместо int get_device_list( device* dev ); Поэтому все и падало....

Я вот еще что не понимаю.
Есть некая функция в some.dll, которая принимает указатель на структурку:
 
Код

struct my_data
{  
     unsigned int data;
};

void init_my_data( my_data* pdata)
{
       pdata->data = 256;
}


Так вот что делаю я :
Код


[StructLayout(LayoutKind.Sequential)]
public class MyData
{
        [MarshalAs(UnmanagedType.U4)]
        public UInt32 number = 0;
}

[DllImport("some.dll")]
public static void init_my_data( IntPtr pdata );

public static int  main()
{
    IntPtr pdata = IntPtr,Zero;
    pdata = Marshal.AllocHGlobal(Marshal.Sizeof(typeof(MyData)));  // здесь pdata получает определенное значение.

    init_my_data(pdata); // Вызов отрабатывает хорошо. НО! После вызова меняется значение pdata!!!

    Marshal.FreeHGlobal(pdata); // Здесь облом, потому что pdata переписан!!!
}


При передаче параметра в функцию как IntPtr он переписывается. Насколько я понимаю так не должно быть и для того чтобы освободить память я сохраняю первоначальное значение в old_pdata, чтобы потом по нему освободить память. Но это коряво.
Подскажите что я неправильно делаю???

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