Пишу обертку для Scilab на с#, руководствуясь включаемыми примерами.
Обертка частично работает на .NET 3.5, например, это работает правильно
/**
* Read named 32-bit integer variable data
* @param[in] _pstName variable name
* @param[out] _piRows return number of rows
* @param[out] _piCols return number of columns
* @param[out] _piData32 return array of 32-bit integers
* @return if the operation succeeded ( 0 ) or not ( !0 )
SciErr readNamedMatrixOfInteger32(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piData32);
*/
[DllImport(DllType.API_SCILAB_DLL, CharSet = CharSet.Ansi)]
public static extern unsafe ApiErr readNamedMatrixOfInteger32([In] IntPtr pvApiCtx, [In] string pstName, [Out] Int32* piRows, [Out] Int32* piCols, [In, Out] int[] piData);
а вот это нет:
/**
* Get named scalar 32-bit integer value
* @param[in] _pstName variable name
* @param[out] _piData return integer value
* @return if the operation succeeded ( 0 ) or not ( !0 )
int getNamedScalarInteger32(void* _pvCtx, const char* _pstName, int* _piData);
*/
[DllImport(DllType.API_SCILAB_DLL, CharSet = CharSet.Ansi)]
public static extern unsafe int getNamedScalarInteger32([In] IntPtr pvApiCtx, [In] String pstName, [Out] Int32* pcData);
причем "P/Invoke Interop Assistant" предлагает более экзотичный вариант, но он тоже не работает.
[System.Runtime.InteropServices.DllImportAttribute(DllType.API_SCILAB_DLL, EntryPoint="readNamedMatrixOfUnsignedInteger32")]
public static extern int readNamedMatrixOfUnsignedInteger32(System.IntPtr _pvCtx,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string _pstName,
ref int _piRows, ref int _piCols, ref uint _puiData32) ;
Самое печальное, что мне надо вызывать свою обертку из .NET 4.0, а в ней не работает вообще ничего (приложение вываливается с ошибкой 0xc0000409 и это не перехватывается), кроме самых примитивных функций, типа
[DllImport(DllType.CALL_SCILAB_DLL, CharSet = CharSet.Ansi)]
public static extern int SendScilabJob([In]String job);
MSDN пишет, почему это происходит — в 4.0 отключено автоматическое исправление неверного объявления вызова неуправляемого кода.
Вопрос — как все-таки правильно маршализовать эти функции?
Re: Проблемы с маршалингом... вываливается 0xc0000409
Что-то у меня подозрение насчет CallingConvention. Можно посмотреть в SCiLab по .h файлам, какой там модификатор : _cdecl или _stdcall ? Можно указать явно в DllImport, например
Re[2]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
31.01.14 07:32
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Аноним, Вы писали:
PD>Что-то у меня подозрение насчет CallingConvention. Можно посмотреть в SCiLab по .h файлам, какой там модификатор : _cdecl или _stdcall ? Можно указать явно в DllImport, например
PD> [DllImport("nat.dll",CallingConvention=CallingConvention.StdCall)]
В Scilab:
надо CallingConvention.Cdecl применять?
странно, что на 3.5 работало
Re[3]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
31.01.14 09:08
Оценка:
Здравствуйте, Аноним, Вы писали:
В общем, в 4.0 работает только из-под отладчика и только из-под hosting process.
Иначе сразу валится с указанным кодом ошибки.
CallingConvention вообще не влияет...
Как это можно победить?
Re[3]: Проблемы с маршалингом... вываливается 0xc0000409
Re[5]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
01.02.14 09:03
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Аноним, Вы писали:
А>>Как это можно победить?
PD>А последовать совету отсюда (совместимость с pre-4.0) пробовал ?
PD>http://msdn.microsoft.com/ru-ru/library/ff361650%28v=vs.100%29.aspx
пробовал, не помогает... к сожалению, никак не понять, что именно он там подкручивает внутри...
выяснилось, что дело в 64-битности — у меня Win7 x64 и есть два набора DLL, для x86 и x64.
в х86 все работает без проблем (с CallingConvention.CDecl, кстати, спасибо ), а с х64 начинает твориться всякая фигня, т.е. там все маршализуется как-то иначе из-за разности размера указателей.
отладчик в VS, как известно, 32-х битный и отладку 64-х битных DLL он как-то реализует, поэтому под ним и работает.
как решить эту проблему пока не нашел, а переводить весь проект в x86 очень не хочется, хотя, если другого выхода не найду — придется.
Re[6]: Проблемы с маршалингом... вываливается 0xc0000409
А>выяснилось, что дело в 64-битности — у меня Win7 x64 и есть два набора DLL, для x86 и x64. А>в х86 все работает без проблем (с CallingConvention.CDecl, кстати, спасибо ), а с х64 начинает твориться всякая фигня, т.е. там все маршализуется как-то иначе из-за разности размера указателей.
Там не только размер указателей. Там еще и нет ни _cdeck, ни _stdcall, а есть своя собственная Calling Convention. Правда, похоже, для нее в этом enum специального значения нет, то есть , я полагаю, годится _cdecl, все равно будет сделано иначе.
Знаешь ли ты C (не надо С++, файл должен быть .c, иначе придется еще с name mangling возиться) ? Если да, то сделай простейшую DLL на С в одной экспортируемой функцией в x64 и попробуй на C# вызвать эту функцию . Может, у этого Mathlab какая-то иная convention ? Вряд ли (на чем он, кстати, написан ?), хотя чем черт не шутит.
А вообще дай кусочек из .h файлов от Mathlab , с объявлением экспортируемой функции.
With best regards
Pavel Dvorkin
Re[7]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
03.02.14 05:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Там не только размер указателей. Там еще и нет ни _cdeck, ни _stdcall, а есть своя собственная Calling Convention. Правда, похоже, для нее в этом enum специального значения нет, то есть , я полагаю, годится _cdecl, все равно будет сделано иначе.
PD>Знаешь ли ты C (не надо С++, файл должен быть .c, иначе придется еще с name mangling возиться) ? Если да, то сделай простейшую DLL на С в одной экспортируемой функцией в x64 и попробуй на C# вызвать эту функцию . Может, у этого Mathlab какая-то иная convention ? Вряд ли (на чем он, кстати, написан ?), хотя чем черт не шутит.
PD>А вообще дай кусочек из .h файлов от Mathlab , с объявлением экспортируемой функции.
Scilab написан на С, С++, Фортране и Java (но то, что я вызываю, написано на обычном C), исходники открыты.
У меня его собрать из них не получается в силу малого знания VC из Visual Studio — чего-то там не находит.
вот объявления функций, которые пытаюсь победить:
/**
* Create named scalar 32-bit integer variable
* @param[in] _pstName variable name
* @param[in] _iData 32-bit integer value
* @return if the operation succeeded ( 0 ) or not ( !0 )
*/int createNamedScalarInteger32(void* _pvCtx, const char* _pstName, int _iData);
#define MESSAGE_STACK_SIZE 5
typedef struct api_Err
{
int iErr; /**< The error ID */int iMsgCount; /**< Error level */char* pstMsg[MESSAGE_STACK_SIZE]; /**< The error message */
} SciErr;
/**
* Read named 32-bit integer variable data
* @param[in] _pstName variable name
* @param[out] _piRows return number of rows
* @param[out] _piCols return number of columns
* @param[out] _piData32 return array of 32-bit integers
* @return if the operation succeeded ( 0 ) or not ( !0 )
*/
SciErr readNamedMatrixOfInteger32(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piData32);
Re[8]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
03.02.14 08:55
Оценка:
под х64 перестала вываливаться, если установить CharSet = CharSet.Auto
но передается (или воспринимается) только первый символ названия переменной
пробовал передавать строку с разными атрибутами, но безуспешно.
Re[8]: Проблемы с маршалингом... вываливается 0xc0000409
Здравствуйте, Аноним, Вы писали:
PD>>Знаешь ли ты C (не надо С++, файл должен быть .c, иначе придется еще с name mangling возиться) ? Если да, то сделай простейшую DLL на С в одной экспортируемой функцией в x64 и попробуй на C# вызвать эту функцию . Может, у этого Mathlab какая-то иная convention ? Вряд ли (на чем он, кстати, написан ?), хотя чем черт не шутит.
Не пробовал ?
With best regards
Pavel Dvorkin
Re[9]: Проблемы с маршалингом... вываливается 0xc0000409
От:
Аноним
Дата:
04.02.14 05:06
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Аноним, Вы писали:
PD>>>Знаешь ли ты C (не надо С++, файл должен быть .c, иначе придется еще с name mangling возиться) ? Если да, то сделай простейшую DLL на С в одной экспортируемой функцией в x64 и попробуй на C# вызвать эту функцию . Может, у этого Mathlab какая-то иная convention ? Вряд ли (на чем он, кстати, написан ?), хотя чем черт не шутит.
PD>Не пробовал ?
нет пока... у меня эта штука в х64 то работает, то нет.
и не могу понять почему, отчего это зависит.
Re[10]: Проблемы с маршалингом... вываливается 0xc0000409
можно передавать строковую переменную через string, char*, char[] и даже Marshal.StringToHGlobalAuto, но обязательно с CharSet = CharSet.Auto или CharSet = CharSet.Unicode.
иначе падает по стеку.
при этом всегда передается только первый символ от строки.
а из функции той же библиотеки, возвращающей char*, результат считывается только через Marshal.PtrToStringAnsi(), иначе абракадабра.
как это обойти — непонятно...