Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> способы передачи аргументов в функцию из unmanaged, ref, out, * и & 
V
    Опции темы
marcusmae
Дата 22.8.2006, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Итак, имеем следующее : unmanaged функция вызывается с аргументами, являющимися экземплярами managed структур. Передавать такие аргументы с * и & запрещено (как мне показалось, из-за возможных плохих эффектов, связанных со сбором мусора). Хорошо. Тогда, передаём инициализированные аргументы через ref, а неинициализированные - через out. В unmanaged функции они нормально пишутся и читиются. Интересно становится, когда эта unmanaged функция вызывает другую unmanaged, передавая те самые аргументы. В ней уже попытка чтения/записи вываливается в виде :

An unhandled exception of type 'System.AccessViolationException' occurred in wrapperGslTest.exe

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 

Что же делать? = Может, нужно передавать аргументы первой unmanaged функции как-то по-другому?


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
mr.DUDA
Дата 22.8.2006, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Судя по всему, это как-то связано с работой P/Invoke со стеком. Большего сказать не могу, потому что не знаю.


--------------------
user posted image
PM MAIL WWW   Вверх
Cr@$h
Дата 22.8.2006, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Цитата(marcusmae @  22.8.2006,  15:59 Найти цитируемый пост)
Интересно становится, когда эта unmanaged функция вызывает другую unmanaged, передавая те самые аргументы. 

А вторая функция случаем не нарушает правил работы с переменными: не читает ли out-параметр или не пишет ли в in-параметр. Вообще, если попал в unmanaged и всё прошло нормально, то дальше можно делать с переменными как с родными, unmanaged.
Второй вопрос -- соглашения о вызовах (calling conventions). Это набор договорённостей о том, как передаются переменные, значим ли регистр, кто зачищает стек переменных после завершения и др. Можно попробовать просто вызывать из первой неуправляемой функции вторую. Может, они и не дружат вовсе...
PM MAIL ICQ   Вверх
marcusmae
Дата 23.8.2006, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Цитата

А вторая функция случаем не нарушает правил работы с переменными: не читает ли out-параметр или не пишет ли в in-параметр.


Функция действительно пишет в ref параметр! Пока не решил, как с этим быть. Дело в том, что она поэлементно копирует матрицу source в матрицу dest, проверяя совпадение размерностей (т.е. dest не может быть out т.к. должен быть инициализирован), вот код :

Код

int
FUNCTION (gsl_matrix, memcpy) (TYPE (gsl_matrix) * dest,
                               const TYPE (gsl_matrix) * src) // прототип формируется макросами
{
  const size_t src_size1 = src->size1;
  const size_t src_size2 = src->size2;
  const size_t dest_size1 = dest->size1;
  const size_t dest_size2 = dest->size2;

  if (src_size1 != dest_size1 || src_size2 != dest_size2)
    {
      GSL_ERROR ("matrix sizes are different", GSL_EBADLEN);
    }

  {
    const size_t src_tda = src->tda ;
    const size_t dest_tda = dest->tda ;
    size_t i, j;

    for (i = 0; i < src_size1 ; i++)
      {
        for (j = 0; j < MULTIPLICITY * src_size2; j++)
          {
            dest->data[MULTIPLICITY * dest_tda * i + j] 
              = src->data[MULTIPLICITY * src_tda * i + j];
          }
      }
  }

  return GSL_SUCCESS;
}


Решил её тоже обернуть для проверки :
Код

        [DllImport("libgsl_d.dll", CallingConvention = CallingConvention.StdCall,
            SetLastError = true)]
        public static extern int gsl_matrix_memcpy(
            [MarshalAs(UnmanagedType.Struct)] ref inst_gsl_matrix Dest,
            [MarshalAs(UnmanagedType.Struct)] ref inst_gsl_matrix Source);


При вызове получил :

Цитата

Windows has triggered a breakpoint in wrapperGslTest.exe.

This may be due to a corruption of the heap, and indicates a bug in wrapperGslTest.exe or any of the DLLs it has loaded.

The output window may have more diagnostic information (ничего подобного)


Значит, ref не является  аналогом *, потому что защищён от записи.  smile Что-то можно придумать, чтобы и инициалирован был, и запись разрешена? = Я пробовал пошаманить с IntPtr. Идея была в том, чтобы с помощью System.Runtime.InteropServices.Marshal сделать unmanaged копии managed структур inst_gsl_matrix  и передавать уже их в качестве аргументов функции. Пока не получается (наверно, следует отдельно задать такой вопрос). 

Цитата

Второй вопрос -- соглашения о вызовах (calling conventions). Это набор договорённостей о том, как передаются переменные, значим ли регистр, кто зачищает стек переменных после завершения и др. Можно попробовать просто вызывать из первой неуправляемой функции вторую. Может, они и не дружат вовсе...


По-моему, не так уж и велик выбор возможных calling conventions. StdCall и Cdecl очищают стек сами (при этом-то и происходит вышеук. ошибка), ThisCall - для работы с классами, FastCall не поддерживается (нужен для мультиплатформенной совместимости, видимо), WinApi = StdCall или Cdecl в зависимости от системы (XP/CE). Так что выбор между StdCall и Cdecl...
Сами функции дружат, т.к. примеры использования на C работают.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
marcusmae
Дата 23.8.2006, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Всё, разобрался, ура. Изменил типы аргументов в прототипе обёртки unmanaged функции на IntPtr, как предлагал Дрон в предыдущей теме, только без всяких ref/out :

Код

        [DllImport("libgsl_d.dll", CallingConvention = CallingConvention.StdCall,
            SetLastError = true)]
        public static extern int gsl_matrix_memcpy(IntPtr Dest, IntPtr Source);


Используя пример из MSDN скопировал структуры в unmanaged memory :

Код

            // initialize unmanged memory to hold the struct
            IntPtr matrixPtr = Marshal.AllocHGlobal(Marshal.SizeOf(matrix));
            IntPtr covMatrixPtr = Marshal.AllocHGlobal(Marshal.SizeOf(covMatrix));

            try
            {
                //  copy the struct to unmanaged memory
                Marshal.StructureToPtr(matrix, matrixPtr, false);
                Marshal.StructureToPtr(covMatrix, covMatrixPtr, false);

                // do unmanaged function call
                wrapperGsl.functions.gsl_matrix_memcpy(covMatrixPtr, matrixPtr);

                // next marshal ptrs back to managed structures
            }
            finally
            {
                //  free  the  unmanaged  memory.
                Marshal.FreeHGlobal(matrixPtr);
                Marshal.FreeHGlobal(covMatrixPtr);
            }


Работает без ошибок в стеке. Спасибо всем!  smile 


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0495 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.