P-invoke, вызов нативной функции из DLL.
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);
public delegate void CALLogFunction(string msg);
[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage", CharSet = CharSet.Ansi)]
public static extern void DisassembleImage(CALimage image, CALLogFunction logfunc);
[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, использующий эту функцию вполне отрабатывает.
Что я делаю не так?
Я если честно не уверен, что она "С".
2) Привести передаваемый делегат к Unmanaged указателю, а его параметр к типу LPSTR
[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage", CharSet = CharSet.Ansi)]
public static extern void DisassembleImage(CALimage image, [MarshalAs(UnmanagedType.FuctionPtr)] CALLogFunction logfunc);
3) Как вариант - написать переходник на MC++
Скиньте плиз dll'ку - самому интересно
Я если честно не уверен, что она "С".
extern "C" - все честно.
2) Привести передаваемый делегат к Unmanaged указателю, а его параметр к типу LPSTR
CLR всегда приводит делегат к UnmanagedType.FuctionPtr при вызовах обычной DLL (но я всеравно попобую этот способ). Для COM+ используется другая конвенция.
Более того, для получения строки я даже использовал sbyte* (и из него руками конструировал System.String). Падение происходит еще до возврата управления делегату. Видимо GC успевает собрать этот делегат, так как не ведает, что указатель на него "уходит" в неуправляемый код.
Вариант не рассматривается в принципе.
ATi Stream SDK. Я разрабатываю способ интеграции этой технологии в .NET. Уже есть кое какой прототип кода, исполняющегося на GPU.
Соглашение по вызову API функции DisassembleXX - это stdcall.
Соглашение по вызову callback функции CALLogFunction - это cdecl.
.NET при маршаллинге делегата видимо используется конвенция вызова "как в DllImport" (т.е. stdcall), отсюда проблема - стек при вызове колбэка очищается некорректно и происходит AV.
Вот и как теперь объяснить маршаллеру соглашение по вызову callback-функции? :(
UPD: Для маршаллинга делегата видимо используется бэкэнд функции Marshal.GetFunctionPointerForDelegate, который делает только stdcall-обертку. :(
CallingConvention=CallingConvention.Cdecl
Импортируемая функция cdecl
А вот как сделать 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);
Только через дизассемблер? или как то есче можно?
Только через дизассемблер? или как то есче можно?
Есть ведь хедеры на C/C++. И куча примеров работы с библиотекой - загрузка когда в GPU, исполнение (на C). По-умолчанию в С используется соглашение cdecl.
public delegate void CALLogFunction([MarshalAs(UnmanagedType.LPTStr)] string msg);
Спасибо! Не нашел такого атрибута (видимо плохо искал!). Приду в оффис - проверю работоспособность. :)
public delegate void CALLogFunction([MarshalAs(UnmanagedType.LPStr)]string msg);
[DllImport(ATICALCL, EntryPoint = "calclDisassembleImage")]
public static extern void DisassembleImage(CALimage image, CALLogFunction logfunc);