Гость
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / взаимодействие с сишной библиотечкой крипотования / 25 сообщений из 37, страница 1 из 2
19.07.2007, 17:25
    #34671160
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Здравствуйте,

У меня просьба проверить синтаксис, так как программа ругается сообщением:
автор"A call to PInvoke function 'TestApplicationForMP!TestApplicationForMP.MP_API::PSE31_Generation' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."
Причем ругается и на PSE31_Generation и на Copy_PSE31


Думаю, что неправильно объявил декларацию функций, но сообразить где проблема, не могу


есть сишная библиотека, в которой объявлены:
автор/* Initialization and Completion Functions */
MPFUN int MPAPI PKCS7Init(char *pse_path, int reserved);
MPFUN int MPAPI PKCS7Final(void);

/* Key and Certificate Request Generation Functions */
MPFUN int MPAPI PSE31_Generation(char *pse_path, int reserv1, char *reserv2, unsigned long flags);
MPFUN int MPAPI Copy_PSE31(char *pse_path, char *reserv, char *new_pse_path, unsigned long flags);



Я написал следующую обертку для dll:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TestApplicationForMP
{
    internal abstract class MP_API
    {
        public const ulong PSE31_FAIL_IF_EXISTS = 1;


        [DllImport("mespro.dll", CharSet = CharSet.Auto)]
        public static extern int PKCS7Init(string Path, int Obsolete);


        [DllImport("mespro.dll", CharSet = CharSet.Auto)]
        public static extern int PKCS7Final();


        [DllImport("mespro.dll", CharSet = CharSet.Auto)]
        public static extern int PSE31_Generation(string PSE_Path, int Reserv1, string Reserv2, ulong Flags);


        [DllImport("mespro.dll", CharSet = CharSet.Auto)]
        public static extern int Copy_PSE31(string PSE_Path, string Reserv, string NewPSE_Path, ulong Flags);
    }
}



Пытаюсь применить следующим образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using TestApplicationForMP;

namespace TestApplicationForMP
{
    class Program
    {
        static void Main(string[] args)
        {
            int i;

            i = MP_API.PKCS7Init(null, 0);
            Console.WriteLine(i);

            i = MP_API.Copy_PSE31(@"c:\Documents and Settings\kazaryan\Мои документы\Message-PRO lib v.2.9.0.10\pse31\u3\", null, @"c:\Documents and Settings\kazaryan\Мои документы\Visual Studio 2005\Projects\Solution1\TestApplicationForMP\bin\Debug\pse31\u3\", 0);
            Console.WriteLine(i);

            i = MP_API.PSE31_Generation(@"c:\Documents and Settings\kazaryan\Мои документы\Visual Studio 2005\Projects\Solution1\TestApplicationForMP\bin\Debug\pse31\u3\", 0, null, 0);
            Console.WriteLine(i);

            i = MP_API.PKCS7Final();
            Console.WriteLine(i);

            Console.Read();
        }
    }
}
...
Рейтинг: 0 / 0
19.07.2007, 17:53
    #34671277
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Если это старя библиотека, то тип int там может быть 16 разрядным, а long 32 разрядным. Соответственно объявления функций надо записать так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
[DllImport("mespro.dll", CharSet = CharSet.Auto)]
public static extern short PKCS7Init(string Path, short Obsolete);

[DllImport("mespro.dll", CharSet = CharSet.Auto)]
public static extern short PKCS7Final();

[DllImport("mespro.dll", CharSet = CharSet.Auto)]
public static extern short PSE31_Generation(string PSE_Path, short Reserv1, string Reserv2, uint Flags);

[DllImport("mespro.dll", CharSet = CharSet.Auto)]
public static extern short Copy_PSE31(string PSE_Path, string Reserv, string NewPSE_Path, uint Flags);
...
Рейтинг: 0 / 0
19.07.2007, 18:07
    #34671341
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
пасиб, так не ругается ))) удивительно, dll скомпилирована в 2005 году, а разрядность старая
...
Рейтинг: 0 / 0
19.07.2007, 18:33
    #34671410
long long
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79пасиб, так не ругается ))) удивительно, dll скомпилирована в 2005 году, а разрядность стараяbazile Вам подсказал верное направление... но не до конца. Сишным 32-битным типам int и unsigned long будут соответствовать c#-ные int и uint. Кроме того, если Ваши сишные функции пишут что-то по указателям на char, то на C# такие параметры следует объявить как StringBuilder, а не string.
...
Рейтинг: 0 / 0
19.07.2007, 19:27
    #34671552
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
учту, хотя StringBuilder - необычно для меня, всегда считал, что это довольно таки сложный класс, и как его можно подставить в параметр как простой указатель на строку - непонятно

Может сделаете еще доброе дело и объясните, как в С# представить параметр void?
Код: plaintext
MPFUN void MPAPI SetKeysPasswordCallbackFunvoid *Func);
...
Рейтинг: 0 / 0
19.07.2007, 20:04
    #34671621
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
void не может быть параметром, а вот void* это нетипизированный указатель или IntPtr в С#.
...
Рейтинг: 0 / 0
20.07.2007, 11:34
    #34672598
long long
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79учту, хотя StringBuilder - необычно для меня, всегда считал, что это довольно таки сложный класс, и как его можно подставить в параметр как простой указатель на строку - непонятноСмысл в том, что если Ваша нативная функция берет char *, который указывает на некоторую область памяти, заранее Вами выделенную, и что-то туда пишет, то такой параметр char * следует представлять как StringBuilder, а перед вызовом такой функции этот StringBuilder нужно создать, причем указать нужный (достаточный) размер. Почему так - строки (string) в .NET - это неизменяемые объекты, а для StringBuilder дотнетовский маршаллер имеет специальную встроенную поддержку. Если же нативная функция не изменяет память, указываемую параметром char *, то можно писать просто string.
...
Рейтинг: 0 / 0
20.07.2007, 11:44
    #34672641
long long
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
long longВот еще это поглядите на предмет интеропа и строковых параметров, там все подробно рассказано.
...
Рейтинг: 0 / 0
23.07.2007, 14:02
    #34677229
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
bazilevoid не может быть параметром, а вот void* это нетипизированный указатель или IntPtr в С#.

Я к чему спрашивал - вижу такое объявление:
Код: plaintext
MPFUN int MPAPI PKCS7Final(void)

именно void без дополнительных символов

я в Си не очень разбираюсь, поэтому сакральный смысл этого объявления оставался для меня скрыт

long longСмысл в том, что если Ваша нативная функция берет char *, который указывает на некоторую область памяти, заранее Вами выделенную, и что-то туда пишет, то такой параметр char * следует представлять как StringBuilder, а перед вызовом такой функции этот StringBuilder нужно создать, причем указать нужный (достаточный) размер. Почему так - строки (string) в .NET - это неизменяемые объекты, а для StringBuilder дотнетовский маршаллер имеет специальную встроенную поддержку. Если же нативная функция не изменяет память, указываемую параметром char *, то можно писать просто string.

Большое спасибо

long longВот еще это поглядите на предмет интеропа и строковых параметров, там все подробно рассказано.
...
Рейтинг: 0 / 0
23.07.2007, 14:11
    #34677263
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79Я к чему спрашивал - вижу такое объявление:
Код: plaintext
MPFUN int MPAPI PKCS7Final(void)

именно void без дополнительных символов

я в Си не очень разбираюсь, поэтому сакральный смысл этого объявления оставался для меня скрыт
Такое объявление говорит что функция PKCS7Final не принимает параметров.
...
Рейтинг: 0 / 0
24.07.2007, 16:47
    #34680873
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Позволю себе продолжить свой ликбез и послушать умных людей

есть ф-ция MPFUN int MPAPI GetSignatureCertInBuffer(void *ctx, int ind, char **buf, int *ln);

про void *ctx я понял, что это IntPtr ctx, так же как и int *ln = IntPtr ln

но как же **? Все равно стрингбилдер (StringBuilder buf)? И как же тогда пользоваться такой функцией?
...
Рейтинг: 0 / 0
24.07.2007, 17:01
    #34680939
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Тип параметра char** означает массив строк. Судя по информации из MSDN (смотри объявление функции TestArrayOfStrings) тип параметра в .NET должен быть
[In, Out]string[] buf
...
Рейтинг: 0 / 0
24.07.2007, 17:05
    #34680955
pinvoke
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79Позволю себе продолжить свой ликбез и послушать умных людей

есть ф-ция MPFUN int MPAPI GetSignatureCertInBuffer(void *ctx, int ind, char **buf, int *ln);

про void *ctx я понял, что это IntPtr ctx, так же как и int *ln = IntPtr ln

но как же **? Все равно стрингбилдер (StringBuilder buf)? И как же тогда пользоваться такой функцией?int *ln - это ref int ln, если *ln не может быть null
char **buf - это ref IntPtr buf, если **buf не может быть null, или просто IntPtr buf, если может. Тут StringBuilder, имхо, не поможет. В последнем случае, кроме того, придется повозиться дополнительно, но непреодолимых препятствий нет. Посмотрите в MSDN про класс Marshal и GCHandle
ПС. Также посмотрите на pinvoke.net, возможно, есть какие-либо системные функции с похожими сигнатурами...
...
Рейтинг: 0 / 0
24.07.2007, 18:18
    #34681258
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
bazileТип параметра char** означает массив строк. Судя по информации из MSDN (смотри объявление функции TestArrayOfStrings) тип параметра в .NET должен быть
[In, Out]string[] buf

pinvokeint *ln - это ref int ln, если *ln не может быть null
char **buf - это ref IntPtr buf, если **buf не может быть null, или просто IntPtr buf, если может. Тут StringBuilder, имхо, не поможет. В последнем случае, кроме того, придется повозиться дополнительно, но непреодолимых препятствий нет. Посмотрите в MSDN про класс Marshal и GCHandle
ПС. Также посмотрите на pinvoke.net, возможно, есть какие-либо системные функции с похожими сигнатурами...

имеет значение char** или char **?

buf есть указатель на указатель на буфер с сертификатом. Буфер может быть выделен пользователем заранее или внутри данной функции. В последнем случае указатель на буфер должен быть равен NULL. Освобождение выделенного буфера осуществляется функцией FreeBuffer

И какое объявление верное?

PS Чертов С, в Delphi все гораздо гораздо проще :) Или привычнее...
...
Рейтинг: 0 / 0
24.07.2007, 18:31
    #34681302
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79имеет значение char** или char **?
Не имеет. Это одно и тоже.

Arm79И какое объявление верное?
У тебя есть описание что делает функция GetSignatureCertInBuffer?
...
Рейтинг: 0 / 0
24.07.2007, 18:33
    #34681311
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
bazile Arm79имеет значение char** или char **?
Не имеет. Это одно и тоже.

Arm79И какое объявление верное?
У тебя есть описание что делает функция GetSignatureCertInBuffer?


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
MPFUN int MPAPI GetSignatureCertInBuffer(void *CTX, int Index, char **Buf, int *Len); 
Данная функция помещает в буфер сертификат, которым проверялась подпись, заданная параметром Index. Параметр Index является индексом элемента в списке цифровых подписей и принимает значения от 0 до N - 1, где N - значение, которое возвращает функция GetSignatureCount.

CTX 	- указатель на контекст, созданный функцией GetSignCTX;
Index 	- индекс цифровой подписи.
Buf 	- указатель на указатель на буфер с сертификатом. Буфер может быть выделен пользователем заранее или внутри данной функции. В последнем случае указатель на буфер должен быть равен NULL. Освобождение выделенного буфера осуществляется функцией FreeBuffer.
Len 	- указатель на размер выделенного пользователем буфера Buf (перед вызовом функции). Игнорируется, если Buf равен NULL. После возврата функции - указатель на длину сертификата в буфере.

Если размер буфера, выделенного пользователем меньше требуемого, то возвращается соответствующая ошибка, а требуемый размер буфера задается параметром Len.
В случае успешного завершения функция возвращает ноль, в случае ошибки - код ошибки.
...
Рейтинг: 0 / 0
24.07.2007, 18:55
    #34681370
pinvoke
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79Buf - указатель на указатель на буфер с сертификатом. Буфер может быть выделен пользователем заранее или внутри данной функции. В последнем случае указатель на буфер должен быть равен NULL. Освобождение выделенного буфера осуществляется функцией FreeBuffer.
Len - указатель на размер выделенного пользователем буфера Buf (перед вызовом функции). Игнорируется, если Buf равен NULL. После возврата функции - указатель на длину сертификата в буфере.Как я и предполагал, char** в данном случае - это не массив строк, а значит, объявление string[] buf, к сожалению, не покатит. Придется все-таки писать ref IntPtr buf. Дальше зависит от того, будете ли Вы сами выделять буфер - то ли с помощью byte[] buffer = new byte[bufferSize]; GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr buf = h.AddrOfPinnedObject(), то ли с помощью IntPtr buf = Marshal.AllocHGlobal(bufferSize) - первый вариант сложнее, но не требует копирования памяти, второй вариант потребует использования Marshal.Copy(), или доверите это Вашей с-шной функции - IntPtr buf = IntPtr.Zero.
...
Рейтинг: 0 / 0
24.07.2007, 19:33
    #34681447
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
pinvoke Arm79Buf - указатель на указатель на буфер с сертификатом. Буфер может быть выделен пользователем заранее или внутри данной функции. В последнем случае указатель на буфер должен быть равен NULL. Освобождение выделенного буфера осуществляется функцией FreeBuffer.
Len - указатель на размер выделенного пользователем буфера Buf (перед вызовом функции). Игнорируется, если Buf равен NULL. После возврата функции - указатель на длину сертификата в буфере.Как я и предполагал, char** в данном случае - это не массив строк, а значит, объявление string[] buf, к сожалению, не покатит. Придется все-таки писать ref IntPtr buf. Дальше зависит от того, будете ли Вы сами выделять буфер - то ли с помощью byte[] buffer = new byte[bufferSize]; GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr buf = h.AddrOfPinnedObject(), то ли с помощью IntPtr buf = Marshal.AllocHGlobal(bufferSize) - первый вариант сложнее, но не требует копирования памяти, второй вариант потребует использования Marshal.Copy(), или доверите это Вашей с-шной функции - IntPtr buf = IntPtr.Zero.

Пасиб за консультацию ))). Думаю, IntPtr buf = IntPtr.Zero - самое то
...
Рейтинг: 0 / 0
26.07.2007, 10:02
    #34684801
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Может порекомендуете ресурсы/книги/статьи по работе с P/Invoke? И по использованию в C# unmanaged code?
...
Рейтинг: 0 / 0
26.07.2007, 10:41
    #34684958
maybeleo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79Может порекомендуете ресурсы/книги/статьи по работе с P/Invoke? И по использованию в C# unmanaged code?В C# "unmanaged code" нет в принципе, есть unsafe - это разные вещи. Насчет ресурсов - в MSDN полно примеров интеропа, а на pinvoke.net - сигнатуры очень многих апишных функций и сопутствующих структур на C# (правда, не всегда удачных, но это поправимо руками). Основные средства при интеропе - MarshalAsAttribute, StructLayoutAttribute, FieldOffsetAttribute, Marshal и GCHandle, да еще ключевое слово fixed в unsafe режиме.
...
Рейтинг: 0 / 0
26.07.2007, 14:44
    #34686099
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
А еще вопросики можно? )

Есть:

Для встраивания библиотеки в Вашу программу (проект) выполните следующее:
- задайте макроопределения MP_DLL и USE_INIT_FLAG;

А как на C# задавать макроопределения?
...
Рейтинг: 0 / 0
26.07.2007, 15:02
    #34686187
Alexes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Задавать-то их можно при помощи #define. Только в C# проекте приведённые Вами определения нужного влияния не окажут. Я так понимаю, эти определения - пользовательские и будут использованы только при компиляции исходников этой библиотеки криптования. А Вы используете уже скомпилированную библиотеку.
...
Рейтинг: 0 / 0
26.07.2007, 15:05
    #34686199
maybeleo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79А как на C# задавать макроопределения?А никак.

Импорт функций и структур возможен только руками (в случае с COM-dll при наличии библиотек типов можно автоматически сгенерировать interop-обертки).

ЗЫ. Если Вас интересуют т.н. preprocessor definitions, то задаются они также - с помощью #define, только в Вашем случае они ничем не помогут.
...
Рейтинг: 0 / 0
26.07.2007, 15:06
    #34686206
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Arm79А как на C# задавать макроопределения?
Практически также как и в C/C++:#define ИМЯ. Отличие в том, что нельзя присвоить этому имени значение как в препроцессоре С/С++.
...
Рейтинг: 0 / 0
26.07.2007, 17:07
    #34686791
Arm79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
взаимодействие с сишной библиотечкой крипотования
Мир не без добрых людей :) Пасиб.

Самаритяне, поясните недалекому:

есть

MPFUN void MPAPI SetRandInitCallbackFun(void *Func);

Данная функция задает пользовательскую функцию обратного вызова RandInitCallback, которая вызывается из библиотеки для инициализации генератора случайных чисел.

Func - указатель на функцию RandInitCallback, реализованную в пользовательском приложении.

Описание функции RandInitCallback следующее:

int _stdcall RandInitCallback(int c, int step, int from, char *reserv);

c – символ, который должен ввести пользователь (должен отображаться на экране);
step – номер текущей итерации;
from – общее число итераций;
reserv – не используется.

Функция RandInitCallback возвращает код введенного пользователем символа (может не совпадать с требуемым символом, в этом случае номер итерации будет уменьшен). Если функция RandInitCallback возвращает -1, процедура инициализации прерывается. Вызов функции RandInitCallback в Windows приложениях осуществляется по правилам языка Pascal (_stdcall).

Пример реализации функции RandInitCallback:

int _stdcall RandInitCallback(int c, int step, int from, char *reserv)
{
unsigned char cc[64];

fprintf(stdout, "Step=%2i/%2i Press %c [%02x]: ", step, from, c, c);
fgets((char *)cc, sizeof(cc), stdin);
if(strcmp((char *)cc, "\n") == 0) return -1;
return *cc;
}

почитав
.NET Framework Developer's Guide
How to: Implement Callback Functions

сделал:

Код: plaintext
public delegate int CallBack(int c, int step, int from, string userdata);

а в классе:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        public static int getch_cb(int c, int step, int from, string userdata)
        {
            // смысл функции - возвратить вызывающей функции код символа, 
            // введенного пользователем. А он вводит то, что ему выдается на экран.
            // то есть можно сразу же возвращать символ
            return c;
        }
        
        [DllImport("mespro.dll", CharSet = CharSet.Auto)]
        public static extern void SetRandInitCallbackFun(CallBack Func);

Применяю:
Код: plaintext
1.
            CallBack Rand = new CallBack(MP_API.getch_cb);
            MP_API.SetRandInitCallbackFun(Rand);

и не работает :)
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / взаимодействие с сишной библиотечкой крипотования / 25 сообщений из 37, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]