Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

P-invoke, вызов нативной функции из DLL.

5
04 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Имеется библиотека (aticalcl.dll), в которой определена следующая функция:
Код:
#define CALAPIENTRY  __stdcall

typedef void (*CALLogFunction)(const char* msg);  /**< Callback function for dissassembler */


/** CAL image container */
typedef struct CALimageRec*  CALimage;


/**
 * @fn calclDisassembleImage(const CALimage image, CALLogFunction logfunc)
 *
 * @brief Disassemble a CAL image.
 *
 * CAL compiler function. Disassembles the CAL image, outputing on a line by line bases to the supplied log function.
 *
 * @param image (in) - image to disassemble.
 * @param logfunc (in) - user supplied function to invoke for each line of disassembly.
 *
 * @return No return
 *
 * @sa calclCompile calclLink
 */
CALAPI void CALAPIENTRY calclDisassembleImage(const CALimage image, CALLogFunction logfunc);
Пытаюсь вызывать её из управляемого кода с помощю следующего объявления (C#):
 
Код:
using CALimage = System.IntPtr;

public delegate void CALLogFunction(string msg);

[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage", CharSet = CharSet.Ansi)]
public static extern void DisassembleImage(CALimage image, CALLogFunction logfunc);
В итоге получаю исключение AccessViolationException:
[quote=CLR]
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at AtiStreamInterop.Platform.CALCL.DisassembleImage(IntPtr image, CALLogFunction logfunc)
[/quote]
Остальные функции, за исключением аналога calclDisassembleObject, работают нормально. Хотя DLL - бетаверсия, но ошибки в функции нет, нативный код на C, использующий эту функцию вполне отрабатывает.

Что я делаю не так?
14
04 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Да скорее всего нативный код отрабатывает просто по случайности. Может эта функция лезет "не туда" и меняет там что-то, просто в нативном случае это не приводит к видимым последствиям. Стек-то после нее в порядке?
842
20 сентября 2009 года
sigmov
301 / / 16.09.2008
1) Функция должна быть в dll в стандарте "С", а не "С++"
Я если честно не уверен, что она "С".
2) Привести передаваемый делегат к Unmanaged указателю, а его параметр к типу LPSTR
 
Код:
public delegate void CALLogFunction ( [MarshalAs(UnmanagedType.LPTStr)] string msg );
[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage", CharSet = CharSet.Ansi)]
public static extern void DisassembleImage(CALimage image, [MarshalAs(UnmanagedType.FuctionPtr)] CALLogFunction logfunc);

3) Как вариант - написать переходник на MC++

Скиньте плиз dll'ку - самому интересно
5
20 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
1) Функция должна быть в dll в стандарте "С", а не "С++"
Я если честно не уверен, что она "С".


extern "C" - все честно.

Цитата: sigmov

2) Привести передаваемый делегат к Unmanaged указателю, а его параметр к типу LPSTR


CLR всегда приводит делегат к UnmanagedType.FuctionPtr при вызовах обычной DLL (но я всеравно попобую этот способ). Для COM+ используется другая конвенция.
Более того, для получения строки я даже использовал sbyte* (и из него руками конструировал System.String). Падение происходит еще до возврата управления делегату. Видимо GC успевает собрать этот делегат, так как не ведает, что указатель на него "уходит" в неуправляемый код.

Цитата: sigmov
Как вариант - написать переходник на MC++

Вариант не рассматривается в принципе.

Цитата: sigmov
Скиньте плиз dll'ку - самому интересно


ATi Stream SDK. Я разрабатываю способ интеграции этой технологии в .NET. Уже есть кое какой прототип кода, исполняющегося на GPU.

5
24 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Нашел причину проблемы.
Соглашение по вызову API функции DisassembleXX - это stdcall.
Соглашение по вызову callback функции CALLogFunction - это cdecl.

.NET при маршаллинге делегата видимо используется конвенция вызова "как в DllImport" (т.е. stdcall), отсюда проблема - стек при вызове колбэка очищается некорректно и происходит AV.

Вот и как теперь объяснить маршаллеру соглашение по вызову callback-функции? :(


UPD: Для маршаллинга делегата видимо используется бэкэнд функции Marshal.GetFunctionPointerForDelegate, который делает только stdcall-обертку. :(
842
25 сентября 2009 года
sigmov
301 / / 16.09.2008
Нужно задать параметр:

CallingConvention=CallingConvention.Cdecl

Импортируемая функция cdecl

А вот как сделать cdecl делегат?
842
25 сентября 2009 года
sigmov
301 / / 16.09.2008
Нашел:
 
Код:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CALLogFunction([MarshalAs(UnmanagedType.LPTStr)] string msg);
[DllImport("aticalcl.dll", EntryPoint = "calclDisassembleImage", CharSet = CharSet.Ansi)]
public static extern void DisassembleImage(IntPtr image,CALLogFunction logfunc);
842
25 сентября 2009 года
sigmov
301 / / 16.09.2008
Кстати, а как имея на руках dll определить тип вызова?

Только через дизассемблер? или как то есче можно?
5
25 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
Кстати, а как имея на руках dll определить тип вызова?

Только через дизассемблер? или как то есче можно?


Есть ведь хедеры на C/C++. И куча примеров работы с библиотекой - загрузка когда в GPU, исполнение (на C). По-умолчанию в С используется соглашение cdecl.

Цитата: sigmov
Нашел:
 
Код:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CALLogFunction([MarshalAs(UnmanagedType.LPTStr)] string msg);


Спасибо! Не нашел такого атрибута (видимо плохо искал!). Приду в оффис - проверю работоспособность. :)

5
25 сентября 2009 года
hardcase
4.5K / / 09.08.2005
ATiшный дизассемблер завелся вот с такими объявлениями:
 
Код:
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate void CALLogFunction([MarshalAs(UnmanagedType.LPStr)]string msg);

[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage")]
public static extern void DisassembleImage(CALimage image, CALLogFunction logfunc);
Выражаю благодарность sigmov. :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог