Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.70/37: Рейтинг темы: голосов - 37, средняя оценка - 4.70
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15

Использование DLL, написанной на delphi

27.04.2015, 07:10. Показов 7945. Ответов 30
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть DLL CscLink.dll, но описание к ней на delphi
Так как в delphi "0", пытаюсь использовать в C#.
Ряд функци уже реализовал из библиотеки, а вот с некоторыми проблема
Так вот сам вопрос. Есть функция
на delphi

Delphi
1
Function CashTransaction( Account: Integer; const Info: TTransactionInfo ): BOOL; stdcall;
на C#

C#
1
2
[DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "CashTransaction")]
public static extern Boolean CashTransaction(int Account, strTTransactionInfo TTransactionInfo);

И соответственно пользовательский тип данных
на delphi

Delphi
1
2
3
4
5
6
7
8
9
10
11
type
  TTransactionInfo = packed record
    Size      : Word;    // Size of TTransactionInfo - заполнить перед вызовом
    Kind      : Word;    // 0-оплата 1-скидка 2-бонус 3-потраты гостя
    Summa     : Comp;    // сумма в копейках
    RestCode  : Word;    // код ресторана
    LogDate   : Integer; // дата чека (0 -> 30/12/1899)
    UnitNum   : Byte;    // номер кассы
    CheckNo   : Integer; // номер чека
    Comment   : Array[0..255] of Char; //комментарий - для ручных транзакций
  end;
Решил перенести как структуру на C#
C#
1
2
3
4
5
6
7
8
9
10
11
public struct strTTransactionInfo
        {
            public ushort Size;    // Size of TTransactionInfo - заполнить перед вызовом
            public ushort Kind;    // 0-оплата 1-скидка 2-бонус 3-потраты гостя
            public Decimal Summa;    // сумма в копейках
            public ushort RestCode;    // код ресторана
            public int LogDate; // дата чека (0 -> 30/12/1899)
            public Byte UnitNum;    // номер кассы
            public int CheckNo; // номер чека
            public char[] Array; //комментарий - для ручных транзакций
        }
объявляю
C#
1
strTTransactionInfo ttr= new strTTransactionInfo();
перед вызовом функции заполняю поля
определяю размерность массива символов
C#
1
ttr.Array = new char[255];
но на вызове функции вылетает ошибка
Тип указанного массива не совпадает с ожидаемым

Помогите разобраться, а то уже голова пухнет.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.04.2015, 07:10
Ответы с готовыми решениями:

Использование функций DLL, написанной на C++
В проекте C# нужно использовать функции, написанные на с++. Создал DLL-ку, все отлично цепляется. Вопрос в том, что в с++ проекте есть своя...

Работа с DLL, написанной на Delphi
Доброго всем времени суток. В C# мягко говоря новичок и, честно признаться, немного не в курсе, реально это вообще или нет. Есть...

Вызов функции из DLL, написанной на Delphi
Здрасте, У меня тут такая ситуация: Рыскал как то я, по просторам интернета, решение 1 проблемы, а именно: рисование своего GUI поверх...

30
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
04.12.2017, 12:26  [ТС]
Студворк — интернет-сервис помощи студентам
И снова возвращаемся к этой же теме. Возникла необходимость вызывать функцию не только с записью структуры, но и считывать структуру, по аналоги с выше изложенным примером(как у gogonk). Структура только другая.
С типами структуры вроде уже разобрались, но возникла проблема при вызове самой функции.
Объявление функции:
C#
1
2
3
4
        
        //Function GetCardUseInfo( Card: Int64; RestCode, UnitNo: Integer; var Info: TCardUseInfo ): BOOL; stdcall;
        [DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCardUseInfo")]
        public static extern Boolean GetCardUseInfo(long Account, int RestCode, int UnitNo, out TCardUseInfo Info);
И пытаюсь вызвать:
C#
1
2
3
4
            
            TCardUseInfo GetInfo = new TCardUseInfo();
            GetInfo.Size = (ushort)Marshal.SizeOf(GetInfo); 
            GetCardUseInfo(3, 0, 0, out GetInfo);
Увы, но выдает пустую структуру, без данных(а они есть 100%)

Тот же подход, только с переменной проходит на ура:

C#
1
2
3
4
       [DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetAccountNumber")]
         public static extern Boolean GetAccountNumber(Int64 Card, out int Account);
....
 GetAccountNumber(b.num, out Acc);
Acc возвращает нужное значение.

Подскажите в какую сторону копать
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
04.12.2017, 12:37
FerRus, может покажете, что за TCardUseInfo ?
0
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
04.12.2017, 12:50  [ТС]
Данные получил(не послал команду логон), но не корректные, походу с типами все же начудил

C#
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
30
31
      
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
 public struct TCardUseInfo
        {
            public ushort Size;  // SizeOf( TAccountInfo )
            public int Account; // номер счёта
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
            public byte[] Holder; //ФИО
            [MarshalAs(UnmanagedType.Bool)]
            public bool Active; // карта активна?
            [MarshalAs(UnmanagedType.Bool)]
            public bool WithMngr; // применять с подтверждением менеджера?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Expired; // истёк срок действия?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Locked; // карта заблокирована?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Seize; // карту изъять
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] WhyLocked; // причина блокировки - asciiz
            public int Unpay; // тип неплательщика
            public ushort Discount;  // номер скидки
            public ushort Bonus;  // номер бонуса
            public long CanPay;
            public long DiscLimit;
            public long Sum1;
            public long Sum2;
            public long Sum3;
            public long Sum4;
            public long Sum5;
        }
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type
  {информация о карте для применения на кассе}
  TCardUseInfo = packed record
    Size       : Word;    // Size of TCardUseInfo - заполнить перед вызовом
    Account    : Integer; // номер счёта
    Holder     : Array[0..40] of Char; // ФИО
    Active     : BOOL;    // карта активна?
    WithMngr   : BOOL;    // применять с подтверждением менеджера?
    Expired    : BOOL;    // истёк срок действия?
    Locked     : BOOL;    // карта заблокирована?
    Seize      : BOOL;    // карту изъять?
    WhyLocked  : Array[0..255] of Char; // причина блокировки - asciiz
    Unpay      : Integer; // тип неплательщика
    Discount   : Word;    // номер скидки
    Bonus      : Word;    // номер бонуса
    CanPay     : Comp;    // сколько можно снять сейчас денег с карты
    DiscLimit  : Comp;    // предел суммы скидки
    Sum1       : Comp;    // остаток на счёте
    Sum2       : Comp;    // остаток на счёте 2 (для Farcards)
    Sum3       : Comp;    // остаток на счёте 3 (для Farcards)
    Sum4       : Comp;    // остаток на счёте 4 (для Farcards)507510784
    Sum5       : Comp;    // остаток на счёте 5 (для Farcards)
  end;

На примере поля Holder, оно текстовое, обрезает первые 2 символа. Соответственно, цифровые значения совсем не те.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
04.12.2017, 15:25
FerRus, ну, выглядит адекватно.

Что могу сказать, попробуйте сначала удалить все непримитивные поля (оставить только long/int), добиться их правильной передачи, а потом постепенно возвращать поля обратно.
1
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
08.12.2017, 13:02  [ТС]
Вообщем вышло так

C#
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
30
        [StructLayout(LayoutKind.Sequential, Pack = 1,CharSet = CharSet.Ansi)]
        public struct TCardUseInfo
        {
            public ushort Size;  // SizeOf( TAccountInfo )
            public int Account; // номер счёта
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)]
            public byte[] Holder; //ФИО
            [MarshalAs(UnmanagedType.Bool)]
            public bool Active; // карта активна?
            [MarshalAs(UnmanagedType.Bool)]
            public bool WithMngr; // применять с подтверждением менеджера?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Expired; // истёк срок действия?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Locked; // карта заблокирована?
            [MarshalAs(UnmanagedType.Bool)]
            public bool Seize; // карту изъять
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] WhyLocked; // причина блокировки - asciiz
            public int Unpay; // тип неплательщика
            public ushort Discount;  // номер скидки
            public ushort Bonus;  // номер бонуса
            public long CanPay;
            public long DiscLimit;
            public long Sum1;
            public long Sum2;
            public long Sum3;
            public long Sum4;
            public long Sum5;
        }
[StructLayout(LayoutKind.Sequential, Pack = 1,CharSet = CharSet.Ansi)]
C#
1
2
        [DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCardUseInfo")]
        public static extern Boolean GetCardUseInfo(long Card, int RestCode, int UnitNo, ref TCardUseInfo Info);
Вместо OUT использовал REF
0
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
22.10.2020, 07:16  [ТС]
Реанимируем тему ))
Прошлые задачи с этой библиотекой работают и по сей день!
Захотелось использовать весь функционал. Так вот застрял на такой конструкции:
Pascal
1
2
3
4
5
6
type
  {процедура обратного вызова для перечисления папок}
  TEnumFolders = Procedure( Id, ParentId: Integer; Deleted: Boolean; Name: PChar ); stdcall;
 
{возврат всех папок}
Function GetAllFolders( Proc: TEnumFolders ): BOOL; stdcall;
Ума не приложу как это может выглядеть в C#.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.10.2020, 11:24
Лучший ответ Сообщение было отмечено FerRus как решение

Решение

FerRus,
type TEnumFolders - это объявление делегата
C#
1
delegate void EnumFolders(int id, int parentId, bool deleted, string name)
с GetAllFolders проблем быть не должно.

Вопрос, а з
1
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
22.10.2020, 12:46  [ТС]
Цитата Сообщение от Psilon Посмотреть сообщение
с GetAllFolders проблем быть не должно.
Все же проблема.
GetAllFolders должен, как я думаю, выдавать список EnumFolders(int id, int parentId, bool deleted, string name)
Как делегат прикрутить не понимаю.
Делегаты в пользовательских событиях только использовал
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.10.2020, 13:18
Лучший ответ Сообщение было отмечено FerRus как решение

Решение

Ну это же коллбек. Так и нужно делать

C#
1
GetAllFolders((id, parentId, deleted, name) => Console.WriteLine(name));
1
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
22.10.2020, 13:56  [ТС]
Спасибо, все работает!

Ну и реализация, чтобы было)
Объявление
C#
1
2
3
        delegate void EnumFolders(int id, int parentId, bool deleted, string name);
        [DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetAllFolders")]
        private static extern Boolean GetAllFolders(EnumFolders Proc);
Класс для хранения

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
public class cFoldersUnit
{
  public int id;
  public int parentId;
  public bool deleted;
  public string name;
  public cFoldersUnit(int _id, int _parentId, bool _deleted, string _name)
  {
    id = _id;
    parentId = _parentId;
    deleted = _deleted;
    name = _name;
  }
}
public static List<cFoldersUnit> FoldersUnit = new List<cFoldersUnit>();
Собственно заполнение класса вызовом метода
C#
1
GetAllFolders((id, parentId, deleted, name) => FoldersUnit.Add(new cFoldersUnit(id, parentId, deleted, name)));
0
20 / 0 / 0
Регистрация: 03.03.2015
Сообщений: 15
10.11.2021, 14:41  [ТС]
Не отпускает меня эта тема )))

Потребовалось запустить следующее
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type
  TTransactionInfo = packed record
    Size      : Word;    // Size of TTransactionInfo - заполнить перед вызовом
    Kind      : Word;    // 0-оплата 1-скидка 2-бонус 3-потраты гостя
    Summa     : Comp;    // сумма в копейках
    RestCode  : Word;    // код ресторана
    LogDate   : Integer; // дата чека (0 -> 30/12/1899)
    UnitNum   : Byte;    // номер кассы
    CheckNo   : Integer; // номер чека
    Comment   : Array[0..255] of Char; //комментарий - для ручных транзакций
  end;
 
type
  {процедура обратного вызова для перечисления транзакций}
  TEnumTransactions = Procedure( Account: Integer; When: TDateTime; const Info: TTransactionInfo ); stdcall;
 
{перечислениe транзакций по счёту, результаты возвращаются через процедуру Proc}
Function GetAccountTransactions( Account: Integer; DateFirst, DateLast: TDateTime; Proc: TEnumTransactions ): BOOL; stdcall;
С типом все просто, уже делали.

C#
1
2
3
4
5
6
7
8
9
10
11
12
        public struct strTTransactionInfo
        {
            public ushort Size;    // Size of TTransactionInfo - заполнить перед вызовом
            public ushort Kind;    // 0-оплата 1-скидка 2-бонус 3-потраты гостя
            public long Summa;    // сумма в копейках
            public ushort RestCode;    // код ресторана
            public int LogDate; // дата чека (0 -> 30/12/1899)
            public byte UnitNum;    // номер кассы
            public int CheckNo; // номер чека
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] Array; //комментарий - для ручных транзакций
         }
По аналоги с EnumFolders рассмотренным ранее.


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        delegate void strTEnumTransactions(int Account, Int64 When, strTTransactionInfo Info);
        [DllImport(DllName, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetAllTransactions")]
        private static extern Boolean GetAllTransactions(Int64 DateFirst, Int64 DateLast, strTEnumTransactions Proc);
        
        private class cTransaction
        {
            int Account;
            Int64 DateWhen;
            strTTransactionInfo TransactionInfo;
 
            public cTransaction(int account, Int64 dateWhen, strTTransactionInfo transactionInfo)
            {
                Account = account;
                DateWhen = dateWhen;
                TransactionInfo = transactionInfo;
            }
        }
И вызываю

C#
1
2
    List<cTransaction> cTransactions = new List<cTransaction>();
    Boolean a = GetAllTransactions(0, 44510, (Account,When,Info) => cTransactions.Add(new cTransaction(Account, When, Info)));
Код не работает.
выдает пустой список

Опять что-то упускаю ((( Есть мысли?

Добавлено через 1 час 18 минут
Цитата Сообщение от FerRus Посмотреть сообщение
И вызываю
Сократил список дат
C#
1
 Boolean a = GetAllTransactions(44508, 44510, (Account,When, Info) => cTransactions.Add(new cTransaction(Account, When, Info)));
и получаю:
"FatalExecutionEngineError" : "В среде выполнения обнаружена критическая ошибка. Ошибка произошла по адресу 0x6dbcf357 в потоке 0x4aac. Код ошибки 0xc0000005.

Добавлено через 8 минут
Цитата Сообщение от FerRus Посмотреть сообщение
public ushort Size;    // Size of TTransactionInfo - заполнить перед вызовом
Проблема я так понимаю в этом.
Но как указать размер типа, у меня экземпляра то нет. Рассчитать внутри типа?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.11.2021, 14:41

Использование DLL, написанной на C++, в C# (указатели)
Всем привет! Есть DLL, написанная на C++, в ней описана такая функция: int ReadData(int kpn,int bn,OUT DWORD*time,OUT...

Использование библиотеки, написанной на Delphi
Здравствуйте, нужно написать длл библиотеку на делфи, и использовать ее в c#, не подскажите простой пример? Как ни делал по примерам из...

Использование Delphi DLL в C#
У меня была цель привязать программу по Harware ID. Воспользовавшись этим:...

Внедрение Dll, написанной на C++ в Exe
Внедрение Dll в Exe (Не взлом! Свою Длл в свою Ехе)... Я создаю в с++ определённую Dll-ky, там есть как бы меню.. Это меню мне нужно...

Импортировать функции из DLL, написанной на C
Добрый день, имеется библиотека, написанная на C. Как её грамотно импортировать в C#. Пока не получается даже создать указатель на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Новости компьютерного мира и их обсуждение (4) Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru