OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 20 Июнь, 2025 16:07

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 5 ] 
Автор Сообщение
 Заголовок сообщения: WideString, PWideChar и соответствие с КП
СообщениеДобавлено: Суббота, 14 Август, 2010 13:29 

Зарегистрирован: Пятница, 25 Сентябрь, 2009 13:10
Сообщения: 1177
Откуда: Мариуполь
Пытаюсь понять внутреннее представление двухбайтовых строк во Free Pascal для использования в Компонентном Паскале внешней библиотеки (написанной на Free Pascal).

Допустим, есть такая библитека:
Код:
Library libtest;

procedure Demo (var b: PWideChar; a: PWideChar); export;
begin
    //a := 'Hello'; // try to set initial value
    b := PWideChar(WideString(a) + '?!');
end;
   
    exports
        Demo;

begin
end.


Теперь пишу на КП модуль описания этой демо-библиотеки:
Код:
MODULE TestLibDll ["libtest"];
   
   TYPE
      Pointer* = POINTER TO RECORD [untagged] END;
      WideString* = ARRAY [untagged] OF CHAR;
      PWideChar* = POINTER TO WideString;
   
   PROCEDURE Demo* (VAR b: PWideChar; a: PWideChar);
   
END TestLibDll.


И сам проверочный модуль:
Код:
MODULE TestDll;

   IMPORT SYSTEM, Lib := TestLibDll, Log := StdLog;
   
   (* int - показывать ли строку также и в числовом виде *)
   PROCEDURE WriteLn(IN s: ARRAY OF CHAR; int: BOOLEAN);
      VAR i: INTEGER;
   BEGIN
      IF int THEN
         FOR i := 0 TO LEN(s$) DO Log.Int(ORD(s[i])) END;
         Log.Ln
      END;
      Log.String("=>" + s  +"<="); Log.Ln;
   END WriteLn;
   
   PROCEDURE StrCpy(OUT dest: Lib.PWideChar; IN src: ARRAY OF CHAR);
      VAR l: INTEGER;
   BEGIN
      WriteLn(" src ", FALSE);
      WriteLn(src, FALSE);
      
      dest := src;
      
      WriteLn(" dest ", FALSE);
      
      (*l := SYSTEM.ADR(dest); Log.Int(l); Log.Ln;*)
      WriteLn(dest$, TRUE);
      
      WriteLn(" end ", FALSE);
   END StrCpy;
   
   PROCEDURE Run*;
      VAR
         a, b: Lib.PWideChar;
         s: ARRAY 64 OF CHAR;
   BEGIN
      StrCpy(a, "++++1234");
      
      WriteLn("===== Demo", FALSE);
      WriteLn(a$, TRUE);
      
      b := NIL;
      Lib.Demo(b, a);
      
      WriteLn(b$, TRUE);
      WriteLn("------ Demo", FALSE);
   END Run;
   
END TestDll.

:!: TestDll.Run

И получаю:
Код:
=> src <=
=>++++1234<=
=> dest <=
 43 43 43 43 49 50 51 52 0
=>++++1234<=
=> end <=
=>===== Demo<=
 43 43 43 43 49 50 51 52 0
=>++++1234<=
 720 63 33 0
=>ː?!<=
=>------ Demo<=

Не пойму что я не учёл. Может, неправильно понял структуру PWideChar...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: WideString, PWideChar и соответствие с КП
СообщениеДобавлено: Суббота, 14 Август, 2010 14:24 

Зарегистрирован: Пятница, 25 Сентябрь, 2009 13:10
Сообщения: 1177
Откуда: Мариуполь
Заменив PWideChar на PAnsiChar в библиотеке и модуле, получил схожий результат.

Зато пример с Free Pascal работает:
Код:
type
    ByteArr = array [0.. 255] of byte;
    PByteArr = ^ByteArr;

const
    Lib = 'libtest.dll';
   
procedure Demo (var b: PWideChar; a: PWideChar); external Lib;
procedure Demo2 (var b: PAnsiChar; a: PAnsiChar); external Lib;

//procedure InsidePWideChar(s: PWideChar);
procedure InsidePAnsiChar(s: PAnsiChar);
var
    t: PByteArr;
    i: integer;
begin
    t := PByteArr(s);
    for i := 0 to 19 do
        write(t^[i]:4);
    writeln;
    for i := 0 to 19 do
        write(chr(t^[i]):4);
    writeln;
end;

var
    //p, s: PWideChar;
    p, s: PAnsiChar;
begin
    writeln('===');
    //p := PWideChar('Hello-');
    p := PAnsiChar('Hello-');
   
    writeln(AnsiString(p));
    //Demo(s, p);
    Demo2(s, p);

    //InsidePWideChar(s);
    InsidePAnsiChar(s);
    //writeln(WideString(s));
    writeln(AnsiString(s));
end.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: WideString, PWideChar и соответствие с КП
СообщениеДобавлено: Суббота, 14 Август, 2010 19:02 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
У ББ стандартное соглашение о вызове - виндовый stdcall. У фрипаскаля какое-то своё. Для Add параметры передаются через eax, edx, ecx. Похоже на борландский fastcall (первые три параметра, если можно, передаются через регистры).
Код:
P$LIBTEST_ADD$PWIDECHAR$PWIDECHAR$PWIDECHAR:
P$LIBTEST_ADD$PWIDECHAR$PWIDECHAR$PWIDECHAR:
; Temps allocated between ebp-68 and ebp-12
; [lib.pas]
; [4] begin
      push   ebp
      mov   ebp,esp
      sub   esp,68
      mov   dword ptr [ebp-68],ebx
; Var a located at ebp-4
; Var b located at ebp-8
; Var c located at ebp-12
      mov   dword ptr [ebp-4],eax
      mov   dword ptr [ebp-8],edx
      mov   dword ptr [ebp-12],ecx
...
Вот как с stdcall (виндовый fpc)
Код:
P$LIBTEST_ADD$PWIDECHAR$PWIDECHAR$PWIDECHAR:
; Temps allocated between ebp-56 and ebp+0
; [lib.pas]
; [4] begin
      push   ebp
      mov   ebp,esp
      sub   esp,56
      mov   dword ptr [ebp-56],ebx
; Var a located at ebp+8
; Var b located at ebp+12
; Var c located at ebp+16
Результат
Вложение:
1.PNG
1.PNG [ 25.68 КБ | Просмотров: 5642 ]
Сорри что картинкой, но командеры в [code] не засушень, а хотелось показать ББ-е тестирование. Роман, как я увидел, использовал самый примитивный вариант с параметрами тестовой процедуры, прошитыми как константы в исходнике. В ББ есть возможность, с минимальными усилиями, эти параметры вынести ниже текста модуля. И отрабатывать без перекомпиляции/перезагрузки модуля.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: WideString, PWideChar и соответствие с КП
СообщениеДобавлено: Суббота, 14 Август, 2010 19:45 

Зарегистрирован: Пятница, 25 Сентябрь, 2009 13:10
Сообщения: 1177
Откуда: Мариуполь
Спасибо за помощь! Вот где собака зарыта...

http://www.freepascal.org/docs-html/pro ... -1600006.3

Цитата:
6.3 Calling mechanism

By default, the calling mechanism the compiler uses is register, that is, the compiler will try to pass as much parameters as posible by storing them in a free register. Not all registers are used, because some registers have a special meaning, but this depends on the CPU.

Function results are returned in the accumulator (first register), if they fit in the register. Methods calls (from either objects or clases) have an additional invisible parameter which is self. This parameter is the leftmost parameter within a method call (it is therefore the last parameter passed to the method).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: WideString, PWideChar и соответствие с КП
СообщениеДобавлено: Суббота, 14 Август, 2010 20:01 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Код:
    END Add;

END TestDll.

ⓘ TestDll.Add
"a" "b"
"aa" "bb"
"123" "456"


Кстати, один из смайликов можно было бы сделать коммандером. Хоть пользу бы приносил. Хотя... Чем :!: не коммандер?


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2025, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB