Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.72/32: Рейтинг темы: голосов - 32, средняя оценка - 4.72
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
.NET 4.x

Как из DLL на Delphi получить значения

15.06.2013, 01:20. Показов 6913. Ответов 50
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Измучался! Понятно - не ас, хоть в VB.Net не первый день. Но уже двое суток бьюсь и никак!
Помогите:
Есть dll написанная в Delphi (с частями исходников), пытаюсь из неё получать информацию и получаю вечные - "PInvoke не возвращает Variable" или разнообразие типа того...
В общем вызываю функции а результат вечно никак...

Вот отрывок кода из Delphi:

Delphi
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
32
33
34
35
36
37
38
39
40
41
42
43
44
Library NativeDll;
 
uses
  SysUtils,
  Windows;
 
type
 
  PImageSet = ^TImageSet;
  TImageSet = packed record
    Size     : Word;
    FileName : Array[0..200] of Char;
  end;
 
  MsgSet = ^TMsgSet;
  TMsgSet = packed record
    Size     : Word;
    Msg      : Array[0..200] of Char;
  end;
 
function GetImage( Card: DWORD; Info: PImageSet ): Integer; stdcall; export;
begin
  Result := 1;
  if Card = 5 then begin
    Result := 0;
    Info^.FileName := 'BOOBLE.BMP';
  end;
end;
 
function GetMessage( Card: DWORD; Info: MsgSet ): Integer; stdcall; export;
begin
  Result := 1;
  if Card in [1..100] then begin
    Result := 0;
    Info^.Msg := 'Привет Васек!';
  end;
end;
 
exports
  GetMessage,
  GetImage;
 
begin
end.
Вызываю примерно так:

VB.NET
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
Imports System
Imports System.Text
Imports System.Runtime.InteropServices
 
Public Class NativeDelphi
 
    Public Structure PImageSet
        Dim Size As Int16
        Dim FFile() As Char ' пробовал всякое
    End Structure
 
    Public Structure MsgSet
        Dim Size As Int16
        Dim Foto() As Char ' пробовал всякое
    End Structure
 
    <DllImport("NativeDll.dll", EntryPoint:="GetImage", _
        CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function GetImage(ByRef Results As PImageSet) As Integer
    End Function
 
    ' и пробовал так
 
    <DllImport("NativeDll.dll", EntryPoint:="GetMessage", CharSet:=CharSet.Auto)> _
    Public Shared Function GetMessage(<MarshalAs(UnmanagedType.LPStr)> ByRef Result As MsgSet)
    End Function
 
End Class
Ошибки да и только. Уж вынес весь мозг. Перепробовал всякое. В инете толковых преобразований Delphi->VB.NET (особенно по поводу packed record и его понимания в VB.NEt, а задом чую - что собака там залежалась) не видать.
В общем если не решу - сопьюсь братцы... (и так литров 15 пива выпил в поиске да кучу сайтов (по сиг с каждого) покурил) Пожалейте здоровие мое!

PS: На счет маршалить - тут я честно говоря лох. Мож чего не так понимаю. Ясно одно - данные из дельфей приходят пакетом вполне упорядоченной структуры и размером, а как его жевать в VB.NET мне пока непонятно.
И есть еще один, для меня пока совсем непонятный тип - PChar (да не, про него я начитался вдоволь, просто непонятно - как его правильно принять из DLL Дельфей в VB.NET, учитывая, что он упакованный) В общем плиз HELP! Заранее ПАСИБО!
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.06.2013, 01:20
Ответы с готовыми решениями:

Получить данные через указатель из dll на delphi
Здравствуйте, помогите пожалуйста! имеется dll, написанная на delphi, где есть процедура: procedure GGetCell(Col : integer; Row :...

Как подключить dll, написанную на C, к dll на Delphi
Добрый день! Нужно подключить dll написанную на C к dll на Delphi. Как это можно сделать и можно ли вообще?

Есть исходник DLL на Delphi как (и возможно ли) написать похожее на VB.NET и использовать в среде программы написанной на Delphi
Суть вопроса вкратце такова - Есть исходник DLL написанной на Delphi Library Extdll; uses SysUtils, Windows; type ...

50
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
15.06.2013, 01:57
RafStudio, проблема действительно в структуре, она у Вас по размеру получается 8 байт на x86 (16 байт на x64) ОС. Если честно очень лень переводить и проверять на VB.NET, но на C# будет так:
C#
1
2
3
4
5
6
7
        [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Ansi /* или Unciode в зависимости от того сколько занимает Char в Delphi */)]
        struct ImageSet
        {
            public ushort Size;
            [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 200 )]
            public string Data;
        }
Добавлено через 2 минуты
Цитата Сообщение от RafStudio Посмотреть сообщение
<MarshalAs(UnmanagedType.LPStr)>
Цитата Сообщение от RafStudio Посмотреть сообщение
, CharSet:=CharSet.Auto
Уберите.
Цитата Сообщение от RafStudio Посмотреть сообщение
EntryPoint:="GetImage", _ CallingConvention:=CallingConvention.Std Call
Это излишне, StdCall используется по умолчанию, и EntryPoint следует использовать только когда название функции в классе должно отличаться от того что нужно импортировать.

Добавлено через 3 минуты
Цитата Сообщение от RafStudio Посмотреть сообщение
Function GetImage
А где первый параметр Card: DWORD?

Добавлено через 29 секунд
Цитата Сообщение от RafStudio Посмотреть сообщение
Function GetMessage
и тут тоже, при этом функция еще возвращает значение, а у Вас нет.
C#
1
2
3
4
5
        [DllImport( "NativeDll.dll" )]
        private static extern int GetImage ( uint card, ref ImageSet info );
 
        [DllImport( "NativeDll.dll" )]
        private static extern int GetMessage ( uint card, ref MsgSet info );
2
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2013, 12:42  [ТС]
ОГРОМЕННЕЙШЕЕ СПАСИБО!
Все заработало!
Использовал все Ваши рекомендации, а за пояснение участков кода и указание на ошибку с CardWORD отдельное спс! Благодаря этому отловил в других функциях свои глупости!

Добавлено через 1 час 31 минуту
Мда... Столкнулся со структурой посложнее и вновь присел...
В существующем исходнике модуля Delphi есть следующие тип и функция его использующие:

Delphi
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
type
  {информация о записи}
  RecordInfo = packed record
    Size            : Word;    // Size of RecordInfo - заполнить перед вызовом
    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;    // остаток 1
    Sum2         : Comp;    // остаток 2
    Sum3         : Comp;    // остаток 3
    Sum4         : Comp;    // остаток 4
    Sum5         : Comp;    // остаток 5
  end;
  {Получение записи из таблицы}
Function GetUseInfo( Card: Int64; RCode, UNo: Integer; var Info: RecordInfo ): BOOL; stdcall;
В VB.NET структуру и вызов оформляю так

VB.NET
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
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
    Public Structure RecordInfo
        Public Size As UShort
        Public Account As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=40)> _
        Public Holder() As String
        Public Active As Boolean
        Public WithMngr As Boolean
        Public Expired As Boolean
        Public Locked As Boolean
        Public Seize As Boolean
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=255)> _
        Public WhyLocked() As String
        Public Unpay As Integer
        Public Discount As UShort
        Public Bonus As UShort
        Public CanPay As Single
        Public DiscLimit As Single
        Public Sum1 As Single
        Public Sum2 As Single
        Public Sum3 As Single
        Public Sum4 As Single
        Public Sum5 As Single
    End Structure
 
    <DllImport(CscLinkLib)> _
    Public Shared Function GetUseInfo(ByVal Card As UInteger, ByVal RCode As Integer, _
                                          ByVal UNo As Integer, ByRef Info As RecordInfo) As Boolean
    End Function
Вызов осуществляю таким образом:

VB.NET
1
2
3
4
5
Dim Info As RecordInfo
        Info.Size = 24
        Info.Holder = {}
        Info.WhyLocked = {}
        GetUseInfo(1, 1, 1, Info)
После чего получаю сообщение о том, что "Не удалось упаковать тип, так как длина внедренного экземпляра массива не соответствует длине, объявленной в макете."
При использовании в UnmanagedType вместо ByValArray ByValTStr - ошибка "поля массивов должны составлять пару с ByValArray или с SafeArray"
При использовании SafeArray - разбалансировка стека...
Боюсь опять встрять на оба выходных с вывихом мозга...
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
15.06.2013, 14:24
Цитата Сообщение от RafStudio Посмотреть сообщение
структуру и вызов оформляю так
Неправильно.
Цитата Сообщение от RafStudio Посмотреть сообщение
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=40)> _
Public Holder() As String
Почему массив стрингов, когда должна быть строка с фиксированной длиной: UnmanagedType.ByValTStr и Holder As String
Цитата Сообщение от RafStudio Посмотреть сообщение
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=255)> _ Public WhyLocked() As String
Аналогично.
Цитата Сообщение от RafStudio Посмотреть сообщение
CanPay : Comp;
Цитата Сообщение от RafStudio Посмотреть сообщение
Public CanPay As Single
Судя по доке Comp это никак не Single, а Int64.
Цитата Сообщение от RafStudio Посмотреть сообщение
Function GetUseInfo( Card: Int64
Цитата Сообщение от RafStudio Посмотреть сообщение
Function GetUseInfo(ByVal Card As UInteger
Должно быть Function GetUseInfo(ByVal Card As Int64 ...
Цитата Сообщение от RafStudio Посмотреть сообщение
Info.Holder = {} Info.WhyLocked = {}
Не нужно
Цитата Сообщение от RafStudio Посмотреть сообщение
Info.Size = 24
Почему 24? Заполняйте так:
C#
1
Info.Size = Marshal.SizeOf(Info);
или
C#
1
Info.Size = Marshal.SizeOf(typeof(RecordInfo));
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2013, 15:03  [ТС]
Блин, и вправду - за массив стрингов точно стыдно!!! (Видать пиво прошлых дней сыграло злую шутку)
Главное - ФУНКЦИЯ РАБОТАЕТ!
Правда все не тестировал, но факт - с Вашими поправками всё отрабатывает без ошибок!
И вновь спасибо огромное за наставления и указания!

Однако, думаю и так понятно, что я не очень силен в типах данных, особенно при понимании их в разных языках,
а потому пару последних вопросов (ну простите за то, что я не очень углубился в Delphi)
Есть еще пара функций в модуле Delphi с которыми у меня как-то не очень...
Выкладывать свои промахи в VB.NET, чтобы кто-то посмеялся - опять красный фломастер... Может сразу тыкнете носом как правильно?

Delphi
1
2
3
4
5
{выполнить подключение к серверу}
Function Login( AUser, APsw: PChar ): BOOL; stdcall;
 
{текст произошедшей ошибки}
Function GetErrorText: PChar; stdcall;
PChar - это как раз именно тот тип, с которым так и не разобрался. (писал в самом начале)

Вопрос - Как бы это выглядело в C# (уж и не прошу в VB.NET )
Пробовал свое и как ожидалось - ну не очень...
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
15.06.2013, 15:12
C#
1
2
3
4
5
6
[DllImport("NativeDll.dll", CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool Login( string user, string psw );
 
[DllImport("NativeDll.dll", CharSet = CharSet.Ansi)]
static extern StringBuilder GetErrorText();
Судя по прототипу Login, строки которые туда передаются не меняются внутри функции, поэтому будет string, если же известно что функция будет модифицировать эти данные, тогда нужно использовать StringBuilder (это на заметку). Если вкратце, то CLR так работает со строками: string используются только на вход (IN), StringBuilder на вход/выход (IN/OUT, OUT).

Цитата Сообщение от RafStudio Посмотреть сообщение
Выкладывать свои промахи в VB.NET, чтобы кто-то посмеялся - опять красный фломастер
Вы не один такой, а пример того как не стоит делать будет многим полезен, сразу будет выявляться место ошибки и возможно понимание почему так не должно быть.
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2013, 19:14  [ТС]
Спасибо - пробую...
А на счет понимания ошибки - это прямо в центр!

Добавлено через 1 час 8 минут
Логин проходит. Все здорово!
Разные версии dll от издателя по разному реагируют, однако суть одна - помощь от Вас 100% оказалась просто неоценимой!
Нет, это не высокопарные слова! Просто жутко-огромное спасибо за СВОЕВРЕММЕНО БЫСТРУЮ помощь!
Надеюсь тему пока не закроют, поскольку наверняка и у меня еще будут вопросы и у таких же мытарей от незнания...

Добавлено через 2 часа 37 минут
И ЕЩЕ РАЗ СПАСИБО!
По сути все победил!!!
В ближайшее время выложу обертку-исходник на VB.NET чтобы всем было просто и понятно использование DLL Delphi на VB.NET
Просто удивительно, что типа такой проблемы нет!!!
Глянешь в Инет - НЕТ ПРОБЛЕМ! - Все живут типа сами по себе!
Ну да ладно!
Самое время говорить: СПАСИБО ОГРОМНОЕ NickoTin за помощь в адаптации кода, за просто своевременную, размеренную и правильную трёпку по шее из за глупостей и ошибок!
Спасибо разработчикам типа UCS, что прячут все от людей и радуют проблемами!
Спасибо людям, что задают вопросы мне, от вышеозначенной и задают вопросы людям которые решают проблемы от вышеозначенной и думают как сделать это хоть местами для себя, но в целом для всех и понятно!
Спасибо cyberforum.ru за возможность сделать все то, о чем сказано выше!
В общем СПАСИБО ВСЕМ!

НО ТЕМА ЕЩЕ ОТКРЫТА! - Вопросов по передаче параметров из DLL Delphi в VB.NET я думаю найдется как у меня, так и многих других представителей умершего языка!
3
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
15.06.2013, 19:22
Цитата Сообщение от RafStudio Посмотреть сообщение
Надеюсь тему пока не закроют
Темы у нас не закрывают, без веской на то причины, не беспокойтесь

Вам спасибо за добрые слова

Не по теме:

з.ы. Если будет интересно, в разделе C# я писал небольшой faq по маршалингу. Возможно поможет в решении некоторых вопросов.

0
1651 / 714 / 47
Регистрация: 11.03.2012
Сообщений: 1,855
Записей в блоге: 1
15.06.2013, 19:23
Цитата Сообщение от RafStudio Посмотреть сообщение
Самое время говорить: СПАСИБО ОГРОМНОЕ NickoTin за помощь в адаптации кода, за просто своевременную, размеренную и правильную трёпку по шее из за глупостей и ошибок!
На то он и модератор этого раздела, "дурака" на это место не поставят.
Цитата Сообщение от RafStudio Посмотреть сообщение
Спасибо cyberforum.ru за возможность сделать все то, о чем сказано выше!
Присоединяюсь.
Цитата Сообщение от RafStudio Посмотреть сообщение
умершего языка!
Про это я думаю ты зря сказал.
0
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2013, 20:11  [ТС]
Цитата Сообщение от Release Посмотреть сообщение
про это я ты думаю зря сказал
я вроде как высказался еще в мертвых (не подумайте плохого)

И еще раз спасибо за своевременность!

Добавлено через 35 минут
Я просто неправильно выразился = "...так и многих других представителей умершего языка!" имелось в ввиду ЧИТАЙ ИЗУЧАЙ которое (к счастью) не умрет никогда!
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
17.06.2013, 20:59  [ТС]
И все же проблема ПРИПЕРЛЛАСЬ:
(устал вуалировать изначальность...), в исходнике на Delphi звучит так:

Delphi
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
32
33
34
35
36
37
38
39
40
type
  {информация о счёте}
  TAccountInfo = packed record
    Size      : Word;    // SizeOf( TAccountInfo )
    Account   : Integer; // номер счёта
    Card      : Int64;   // номер карты
    Holder    : Array[0..40] of Char; //ФИО
    Scheme    : Byte;    {тип счёта: 
                          0 - ручное пополнение без ограничения оплат
                          1 - автоматическое пополнение без ограничения оплат
                          2 - автоматическое пополнение с лимитом оплат на один день
                          3 - автоматическое пополнение с лимитом оплат на неделю
                          4 - автоматическое пополнение с лимитом оплат на месяц
                          5 - ручное пополнение с лимитом оплат на один день
                          6 - ручное пополнение с лимитом оплат на неделю
                          7 - ручное пополнение с лимитом оплат на месяц
                          }
    Offered   : Integer; // дата выдачи (0 -> 30/12/1899)
{*} Expired   : Integer; // срок действия
{*} Birthday  : Integer; // день рождения
    Deleted   : BOOL;    // счёт удален?
{*} Locked    : BOOL;    // карта заблокирована?
{*} Seize     : BOOL;    // карту изъять?
{*} WhyLocked : Array[0..255] of Char; // причина блокировки - asciiz
    Discount  : Word;    // номер скидки
{*} Bonus     : Word;    // номер бонуса
    PayLimit  : Comp;    // лимит оплат для счетов c лимитом
{*} Female    : BOOL;    // пол
    Folder    : Word;    // идентификатор отдела
    Unpay     : Integer; // номер неплательщика
{*} Tel1      : Array[0..15] of Char; //телефон 1
{*} Tel2      : Array[0..15] of Char; //телефон 2
{*} Email     : Array[0..255] of Char;
{*} Address   : Array[0..255] of Char;
{*} DopInfo   : Array[0..255] of Char; //произвольная информация - asciiz
    Balance   : Comp;    // для карт с ручным пополнением - текущий остаток
  end;
 
{получить информацию о счёте}
Function GetAccountInfo( Account: Integer; var Info: TAccountInfo ): BOOL; stdcall;
символами {*} отмечены изменяемые поля другой функцией
В варианте, с Вашей помощью, звучит так:

VB.NET
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    ' === ИНФОРМАЦИЯ О СЧЕТЕ ===
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
    Public Structure TAccountInfo
        'Size of TAccountInfo - заполнить перед вызовом
        Public Size As UShort
        ' Номер счёта
        Public Account As Integer
        ' Номер карты
        Public Card As Int64
        ' Фамилия Имя Отчество
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=40)> _
        Public Holder As String
        ' Тип счета:
        '   0 - ручное пополнение без ограничения оплат
        '   1 - автоматическое пополнение без ограничения оплат
        '   2 - автоматическое пополнение с лимитом оплат на один день
        '   3 - автоматическое пополнение с лимитом оплат на неделю
        '   4 - автоматическое пополнение с лимитом оплат на месяц
        '   5 - ручное пополнение с лимитом оплат на один день
        '   6 - ручное пополнение с лимитом оплат на неделю
        '   7 - ручное пополнение с лимитом оплат на месяц
        Public Scheme As Byte
        ' Дата выдачи (0 -> 30/12/1899)
        Public Offered As Integer
        ' Срок действия {*}
        Public Expired As Integer
        ' День рождения {*}
        Public Birthday As Integer
        ' Счет удален?
        Public Deleted As Boolean
        ' Карта заблокирована? {*}
        Public Locked As Boolean
        ' Карту изъять? {*}
        Public Seize As Boolean
        ' Причина блокировки - asciiz {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=255)> _
        Public WhyLocked As String
        ' Номер скидки
        Public Discount As UShort
        ' Номер бонуса {*}
        Public Bonus As UShort
        ' Лимит оплат для счетов c лимитом
        Public PayLimit As Int64
        ' Пол {*}
        Public Female As Boolean
        ' Идентификатор отдела
        Public Folder As UShort
        ' Номер неплательщика
        Public Unpay As Integer
        ' Телефон 1 {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=15)> _
        Public Tel1 As String
        ' Телефон 2 {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=15)> _
        Public Tel2 As String
        ' Электронная почта {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=255)> _
        Public Email As String
        ' Адрес {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=255)> _
        Public Address As String
        ' Произвольная информация - asciiz {*}
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=255)> _
        Public DopInfo As String
        ' Для карт с ручным пополнением - текущий остаток
        Public Balance As Int64
    End Structure
Проблема в возвращении массивов = например Holder возвращает минус 2 символа/байта, а следующий массив WhyLocked -минус четыре. Итогом слов ФИО = вместо "Васек" = "сек", а причина блокировки "Да просто так хотелось" получается = "росто так хотелось"
Прирост потери по паре байт(символов) - в возвращаемых массивах - на лицо. Мало того, по наблюдениям они увеличиваются в структуре от массива к массиву. Найти решение пока не удалось...

Добавлено через 8 минут
В общем отловить потерянных два символа/байта пока не удалось...
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
17.06.2013, 21:01
VB.NET
1
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Попробуйте.
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
17.06.2013, 21:08  [ТС]
Цитата Сообщение от NickoTin Посмотреть сообщение
VB.NET
1
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Попробуйте.
Это что?!!! Юстас -> Алексу?!!!
Ну блин, что еще сказать - ЗАРАБОТАЛО!

Можно хоть немного комментариев?!!

(понятно - надо больше читать...)
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
17.06.2013, 21:14
Цитата Сообщение от RafStudio Посмотреть сообщение
Это что?
Pack. Указывает выравнивание полей структуры в памяти. В Delphi проекте библиотеки видимо так настроено, что поля выравниваются по границе 1 байта, т.е. между полями не будет промежутков, это порой не оптимально для скорости выполнения, но уменьшает размер структуры в памяти.
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
17.06.2013, 21:17  [ТС]
Суть понятна - решение выполнено еще в DOS => Просто поддерживается до сих пор в Win...

PS: Имелось ввиду решение владельца DLL с выложенной частью исходника для коннекта...

Очередное спасибо!
Но все же чуйствую - впереди вопросы по Enumerate...
0
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
18.06.2013, 21:43  [ТС]
Сначала недопонимал, с чем связанны дурацкие возвраты функций относительно значений возвращаемых из структур типа
VB.NET
1
UnmanagedType.ByValTStr
и как следствие - полный бред для всех получаемых данных из структуры после данных типов.
Сегодня понял - если в Delphi параметр равен например
Delphi
1
Array[0..255] of Char
то в VB.NET будет
VB.NET
1
UnmanagedType.ByValTStr, SizeConst:=256
что собственно и логично! (Вы NickoTin видимо специально оставили маленький подвох в своих подсказках для моего саморазвития!)
2
19.06.2013, 15:43

Не по теме:

Цитата Сообщение от RafStudio Посмотреть сообщение
Вы NickoTin видимо специально оставили маленький подвох в своих подсказках для моего саморазвития
Нет, я просто не знаю Delphi )

0
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
19.06.2013, 21:05  [ТС]
Есть одна (для меня пока не критичная) ПРОЦЕДУРА в Delphi, использование которой несколько раз (без разницы в течение какого времени) вызывает "неуправляемую" ошибку "Попытка чтения или записи в защищенную память". "Неуправляемую" - в смысле для меня, поскольку перед её вызовом я вроде обрамляю все в Try-Catch однако при отладке интерпретатор встает! Не столь остро, но всё же вызывает интерес:

Delphi
1
2
{отключение от сервера}
Procedure Done;
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<DllImport(NativeDll, EntryPoint:="Done")> _
    Private Shared Sub p_Done()
    End Sub
 
    Public Shared Function Done() As Boolean
        Try
            p_Done()
            NativeDll.LastMsg = "The connection is closed"
            Return True
        Catch e As Exception
            NativeDll.LastMsg = e.ToString
            Return False
        End Try
    End Function
Конечно, возможно ошибка связана с тем, что DLL издателя все же что-то творит там с возвратом значений, и бог его знает еще чего. Но в первую очередь грешится на себя. Уж больно издатель знаменит...

Добавлено через 9 минут
Не обращайте внимания на запись типа
VB.NET
1
NativeDll.LastMsg
Печатал вручную, и ошибся. Воспринимайте как
VB.NET
1
LinkDll.LastMsg
LinkDll - это данный класс, в котором объявлено это свойство

Добавлено через 5 минут
Тьфу, но ведь не может это быть связано с тем, что я из функции вызываю процедуру?
Тем более, морда лица приложения говорит о том, что я все же отконнектился от сервера...
То есть вызванная процедура была вроде как выполнена...
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
22.06.2013, 03:46
Цитата Сообщение от RafStudio Посмотреть сообщение
возможно ошибка связана с тем, что DLL издателя все же что-то творит там с возвратом значений
Возможно, нужно либу смотреть...
Цитата Сообщение от RafStudio Посмотреть сообщение
Тьфу, но ведь не может это быть связано с тем, что я из функции вызываю процедуру?
Не может.
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
25.06.2013, 19:24  [ТС]
После некоторой передышки, ( а точнее - поглощением работой), вновь засел за проект и столкнулся с некоторыми для меня непонятностями.
В Delphi существует функция GetAccountInfo которая заполняет структуру TAccountInfo и прекрасно работает, возвращая данные в VB.NET. Так-же есть функция SetAccountInfo которая по определению сохраняет изменения произведенные в структуре TAccountInfo. (Следует отметить - для чистоты я в принципе ничего не меняю в полученных данных, сразу же вызываю SetAccountInfo) Обращение в Дельфях выглядит так:

Delphi
1
2
3
4
5
{получить информацию о счёте}
Function GetAccountInfo( Account: Integer; var Info: TAccountInfo ): BOOL; stdcall;
 
{Перед вызовом сперва заполнить Info вызовом GetAccountInfo()}
Function SetAccountInfo( const Info: TAccountInfo ): BOOL; stdcall;
Info - однозначно заполнена. Что меня смущает, так это "const Info: Структура"
Однако в VB.NET константа не может быть структурой! И вот я как-то присел тихо... Почесал тыковку - может через перечисления? Но тут я увы не очень. В общем простота типа:

VB.NET
1
2
3
4
5
6
7
8
9
10
    ' Получить информацию о счете
    <DllImport(CscLinkLib, EntryPoint:="GetAccountInfo")> _
    Private Shared Function p_GetAccountInfo(ByVal Account As Integer, ByRef Info As TAccountInfo) As Boolean
    End Function
 
    ' Изменить параметры счета. Изменяются парметры помеченные знаком {*} в структуре TAccountInfo
    ' Перед вызовом сперва заполнить Info вызовом функции GetAccountInfo()
    <DllImport(CscLinkLib, EntryPoint:="SetAccountInfo")> _
    Private Shared Function p_SetAccountInfo(ByVal Info As TAccountInfo) As Boolean
    End Function
приводит к разбалансированию стека... Мммм...
(Использование EntryPoint:= продиктовано оборачиванием всего этого хозяйства в класс для удобства)
Please Help!

Добавлено через 42 минуты
Цитата Сообщение от RafStudio Посмотреть сообщение
(Использование EntryPoint:= продиктовано оборачиванием всего этого хозяйства в класс для удобства)
Это я к тому, что как и обещал - в итоге проделанной работы, выложу исходник VB.NET для работы с функциями из DLL написанной на Delphi, в котором будет просто и наглядно описано решение проблем возникающих при использовании данного типа внешних DLL. Но в процессе выяснилось, что даже вызов задекларированных функций может вызывать некоторые осложнения. Как следствие - почему бы не создать обертку, позволяющую более наглядно, на примере живой DLL, рассмотреть данные вопросы. Тем более, как я уже говорил в начале топика - информация в Интернет (лично для меня) показалась не слишком освещенной в данном направлении.

(Думаю не оффтоп)

А вообще - речь идет о весьма серьезном игроке на рынке автоматизации бизнеса - компании UCS. Давно уж собирался с мыслями в эту сторону. Ну вот собственно созрел и начал разработку некоторых модулей уже с учетом запросов пользователей, являющихся клиентами.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.06.2013, 19:24
Помогаю со студенческими работами здесь

Как средствами RTTI получить указатель на ComponentArray[0] или как получить значения некоторых свойств?
type TTestComponentItem = class(TComponent) end; TComponentArray = array of TTestComponentItem; TTestComponent =...

Как иcследовать DLL написанную на С++, Delphi?
Как иcследовать DLL написанную на С++, Delphi?

Как использовать в Delphi dll из .Net
Всем здравствуйте. Задача: разработать библиотечное приложение (работа с библиотечным сервером и субд oracle). Для работы с...

TableView Получить значения из ячеек в таблице, и присвоить эти значения переменным, а потом получить их сумму
есть код таблицы из примера с оф сайта docs.oracle как можно получить и присвоить переменной цифровое значение введенное в одну из...

Как получить HANDLE server.dll?(GetModuleHandle(L"server.dll") возвращает нули )
Мне необходимо получить HANDLE server.dll для ReadProcessMemory и WriteProcessMemory ,GetModuleHandle(L&quot;server.dll&quot;) возвращает нули...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru