Проблемы с маршалингом... вываливается 0xc0000409
От: Аноним  
Дата: 30.01.14 08:29
Оценка:
Всем привет!

Пишу обертку для 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
От: Pavel Dvorkin Россия  
Дата: 30.01.14 15:15
Оценка:
Здравствуйте, Аноним, Вы писали:


Что-то у меня подозрение насчет CallingConvention. Можно посмотреть в SCiLab по .h файлам, какой там модификатор : _cdecl или _stdcall ? Можно указать явно в DllImport, например

[DllImport("nat.dll",CallingConvention=CallingConvention.StdCall)]
With best regards
Pavel Dvorkin
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:
#ifdef _MSC_VER
#ifndef API_SCILAB_EXPORTS
    __declspec( dllimport ) StrCtx* pvApiCtx;
#else
    extern StrCtx* pvApiCtx;
#endif
#else
    extern StrCtx* pvApiCtx;
#endif

надо CallingConvention.Cdecl применять?
странно, что на 3.5 работало
Re[3]: Проблемы с маршалингом... вываливается 0xc0000409
От: Аноним  
Дата: 31.01.14 09:08
Оценка:
Здравствуйте, Аноним, Вы писали:

В общем, в 4.0 работает только из-под отладчика и только из-под hosting process.
Иначе сразу валится с указанным кодом ошибки.
CallingConvention вообще не влияет...
Как это можно победить?
Re[3]: Проблемы с маршалингом... вываливается 0xc0000409
От: Pavel Dvorkin Россия  
Дата: 01.02.14 04:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А> __declspec( dllimport ) StrCtx* pvApiCtx;


Это импорт переменной, а не функции. К переменным CallingConvention неприменима.
With best regards
Pavel Dvorkin
Re[4]: Проблемы с маршалингом... вываливается 0xc0000409
От: Pavel Dvorkin Россия  
Дата: 01.02.14 04:44
Оценка: 6 (1)
Здравствуйте, Аноним, Вы писали:

А>Как это можно победить?


А последовать совету отсюда (совместимость с pre-4.0) пробовал ?

http://msdn.microsoft.com/ru-ru/library/ff361650%28v=vs.100%29.aspx
With best regards
Pavel Dvorkin
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
От: Pavel Dvorkin Россия  
Дата: 01.02.14 10:15
Оценка:
Здравствуйте, Аноним, Вы писали:


А>выяснилось, что дело в 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
От: Pavel Dvorkin Россия  
Дата: 03.02.14 12:30
Оценка:
Здравствуйте, Аноним, Вы писали:

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
От: Аноним  
Дата: 05.02.14 05:54
Оценка:
в общем, не работает...
на x64 в функцию
SciErr readNamedMatrixOfInteger32(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piData32

можно передавать строковую переменную через string, char*, char[] и даже Marshal.StringToHGlobalAuto, но обязательно с CharSet = CharSet.Auto или CharSet = CharSet.Unicode.
иначе падает по стеку.
при этом всегда передается только первый символ от строки.
а из функции той же библиотеки, возвращающей char*, результат считывается только через Marshal.PtrToStringAnsi(), иначе абракадабра.
как это обойти — непонятно...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.