powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / взаимодействие с сишной библиотечкой крипотования
25 сообщений из 37, страница 1 из 2
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34671341
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пасиб, так не ругается ))) удивительно, dll скомпилирована в 2005 году, а разрядность старая
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34671410
long long
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arm79пасиб, так не ругается ))) удивительно, dll скомпилирована в 2005 году, а разрядность стараяbazile Вам подсказал верное направление... но не до конца. Сишным 32-битным типам int и unsigned long будут соответствовать c#-ные int и uint. Кроме того, если Ваши сишные функции пишут что-то по указателям на char, то на C# такие параметры следует объявить как StringBuilder, а не string.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34671552
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
учту, хотя StringBuilder - необычно для меня, всегда считал, что это довольно таки сложный класс, и как его можно подставить в параметр как простой указатель на строку - непонятно

Может сделаете еще доброе дело и объясните, как в С# представить параметр void?
Код: plaintext
MPFUN void MPAPI SetKeysPasswordCallbackFunvoid *Func);
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34671621
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
void не может быть параметром, а вот void* это нетипизированный указатель или IntPtr в С#.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34672598
long long
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arm79учту, хотя StringBuilder - необычно для меня, всегда считал, что это довольно таки сложный класс, и как его можно подставить в параметр как простой указатель на строку - непонятноСмысл в том, что если Ваша нативная функция берет char *, который указывает на некоторую область памяти, заранее Вами выделенную, и что-то туда пишет, то такой параметр char * следует представлять как StringBuilder, а перед вызовом такой функции этот StringBuilder нужно создать, причем указать нужный (достаточный) размер. Почему так - строки (string) в .NET - это неизменяемые объекты, а для StringBuilder дотнетовский маршаллер имеет специальную встроенную поддержку. Если же нативная функция не изменяет память, указываемую параметром char *, то можно писать просто string.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34672641
long long
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
long longВот еще это поглядите на предмет интеропа и строковых параметров, там все подробно рассказано.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34677263
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79Я к чему спрашивал - вижу такое объявление:
Код: plaintext
MPFUN int MPAPI PKCS7Final(void)

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

я в Си не очень разбираюсь, поэтому сакральный смысл этого объявления оставался для меня скрыт
Такое объявление говорит что функция PKCS7Final не принимает параметров.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34680939
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тип параметра char** означает массив строк. Судя по информации из MSDN (смотри объявление функции TestArrayOfStrings) тип параметра в .NET должен быть
[In, Out]string[] buf
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34681302
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79имеет значение char** или char **?
Не имеет. Это одно и тоже.

Arm79И какое объявление верное?
У тебя есть описание что делает функция GetSignatureCertInBuffer?
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34684801
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может порекомендуете ресурсы/книги/статьи по работе с P/Invoke? И по использованию в C# unmanaged code?
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
взаимодействие с сишной библиотечкой крипотования
    #34686099
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А еще вопросики можно? )

Есть:

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

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

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

ЗЫ. Если Вас интересуют т.н. preprocessor definitions, то задаются они также - с помощью #define, только в Вашем случае они ничем не помогут.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #34686206
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79А как на C# задавать макроопределения?
Практически также как и в C/C++:#define ИМЯ. Отличие в том, что нельзя присвоить этому имени значение как в препроцессоре С/С++.
...
Рейтинг: 0 / 0
взаимодействие с сишной библиотечкой крипотования
    #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
25 сообщений из 37, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / взаимодействие с сишной библиотечкой крипотования
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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