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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обёртка для функций из dll на С, передаются неправильные аргументы 
V
    Опции темы
marcusmae
  Дата 21.8.2006, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Хочу научиться делать wrapper'ы для функций из unmanaged dll на С.
Имею там функцию :

Код

int
gsl_multifit_linear (const gsl_matrix * X,
                     const gsl_vector * y,
                     gsl_vector * c,
                     gsl_matrix * cov,
                     double *chisq, gsl_multifit_linear_workspace * work)
{
  size_t rank;
  int status;

  status = gsl_multifit_linear_svd (X, y, GSL_DBL_EPSILON, &rank, c,
                                        cov, chisq, work);
  return status;
}


Для вызова из managed использую DllImport :

Код

        [DllImport("libgsl_d.dll", CallingConvention = CallingConvention.StdCall,
            SetLastError = true)]
        unsafe public static extern int gsl_multifit_linear(ref inst_gsl_matrix X,
            ref inst_gsl_vector y, ref inst_gsl_vector c, ref inst_gsl_matrix cov,
            ref double chisq, ref inst_gsl_multifit_linear_workspace work);


Используемые типы gsl_matrix, gsl_vector, gsl_multifit_linear_workspace нужно писать заново, потому что из dll их не извлечь (поправьте, если неправ), поэтому создал всё "близко к тесту", добавив конструкторы :

1) структуру

Код

struct gsl_block_struct
{
  size_t size;
  double *data;
};


переписал так :

Код

    [StructLayout(LayoutKind.Sequential)]
    public class inst_gsl_block_struct
    {
        ulong size;
        double[] data;

        public inst_gsl_block_struct(ulong size, ref double[] data)
        {
            this.size = size; this.data = data;
        }
    }


2) структуру

Код

typedef struct 
{
  size_t size1;
  size_t size2;
  size_t tda;
  double * data;
  gsl_block * block;
  int owner;
} gsl_matrix;


переписал так :

Код

    [StructLayout(LayoutKind.Sequential)]
    public class inst_gsl_matrix
    {
        ulong size1;
        ulong size2;
        ulong tda;
        double[] data;
        inst_gsl_block_struct block;

        public inst_gsl_matrix(ulong size1, ulong size2, ulong tda, 
            ref double[] data, ref inst_gsl_block_struct block)
        {
            this.size1 = size1; this.size2 = size2; this.tda = tda;
            this.data = data; this.block = block;
        }
    }


3) структуру

Код

typedef struct 
{
  size_t size;
  size_t stride;
  double *data;
  gsl_block *block;
  int owner;
} 
gsl_vector;


переписал так :

Код

    [StructLayout(LayoutKind.Sequential)]
    public class inst_gsl_vector
    {
        ulong size;
        ulong stride;
        double[] data;
        inst_gsl_block_struct block;
        int owner;

        public inst_gsl_vector(ulong size, ulong stride, ref double[] data,
            ref inst_gsl_block_struct block, int owner)
        {
            this.size = size; this.stride = stride; this.data = data;
            this.block = block; this.owner = owner;
        }
    }


Так вот, при попытке обращения к gsl_multifit_linear из управляемого кода, портятся параметры, передаваемые по ссылке. Например, X.size1 = 2, X.size2 = 2
приходит в unmanaged gsl_multifit_linear в виде X->size1 = 17235980,
X->size2 = 10893332.
Подскажите, пожалуйста, как получить верные параметры.





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


Пуфыстый назгул
****


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

Репутация: 14
Всего: 42



Если пердаете парметр по ссылке, то и получать надо ссылку. 
Код

 [DllImport("libgsl_d.dll", CallingConvention = CallingConvention.StdCall,
            SetLastError = true)]
        unsafe public static extern int gsl_multifit_linear(ref IntPtr X,
            ref IntPtr y, ref IntPtr c, ref IntPtr cov,
            ref IntPtr chisq, ref IntPtr work);


Затем методом Marshal.GetObjectForIUnknown или сходными получаешь обьект и приводьшь к твоему типу.

Добавлено @ 16:06 
Или я что-то не так понял?
PM MAIL   Вверх
marcusmae
Дата 21.8.2006, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Перемудрил. Оказывается, нужно было типы переписывать как struct, а не как class. Кроме того, важен аттрибут [StructLayout(LayoutKind.Sequential)]  - при отсутствии возникает memory corrupt.

Тоже, подумал, что ещё понадобятся [MarshalAs(UnmanagedType.*)], но вроде пока не понадобились.

Теперь структуры нормально передаются (без всяких IntPtr), ерунда пока получается только в параметре

Код

ref double chisq


Это сообщение отредактировал(а) marcusmae - 21.8.2006, 16:14


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


Java-ненавистник :)
****


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

Репутация: 24
Всего: 93



marcusmae, 
походу дела size_t это unsigned int (т.е. 32-битный), а вот ulong в .NET имеет размер 64 бита, так что на самом деле надо было использовать uint.

Это сообщение отредактировал(а) Дрон - 21.8.2006, 17:23


--------------------
Да. Именно так.
PM   Вверх
marcusmae
Дата 21.8.2006, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



да, спасибо, это я тоже уже исправил.

Проблема в данный момент заключается в
An unhandled exception of type 'System.AccessViolationException'
видимо, при попытке неуправляемого кода писать по переданным функции ссылкам.

Это сообщение отредактировал(а) marcusmae - 21.8.2006, 17:43


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


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


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

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



Цитата(marcusmae @  21.8.2006,  17:41 Найти цитируемый пост)
видимо, при попытке неуправляемого кода писать по переданным функции ссылкам.

Может, для простых типов пойдёт не "ref double" а "double *" ?


--------------------
user posted image
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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