Есть решение?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Сообщение Saemon Zixel » 21.04.2006 20:30:00

Доброе время суток!

var
a: integer;
b: integer;

procedure test(p : pointer);
begin
@a:=p;
end;

begin
b:=2;
test(@b);
end.

Какими путями надо пойти чтоб a и b были именами одной ячейки памяти?
Может ли freepascal своими расширениями подобное осуществить?
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение virt » 22.04.2006 13:53:15

Код: Выделить всё
var a : integer;
   b : integer absolute a;

begin
  a := 10;
  writeln(b);
end.


Или надо чтобы во время исполнения присваивалось?
virt
новенький
 
Сообщения: 35
Зарегистрирован: 01.12.2005 12:31:41

Сообщение Saemon Zixel » 22.04.2006 17:24:34

Про absalute я уже знаю.
Просто я пишу библеотеку, каторая использует несколько массивов, а массивы создаёт и заполняет программа использующую эту библеотеку.
И чтобы не вставлять теперь везде ^ я хотел сменить указатели переменных на переданные массивы.
Но видать такое freepascal не умеет. жалль <_<
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение volvo877 » 22.04.2006 17:55:25

Saemon Zixel,
напиши, КАК ты хочешь передавать параметры в библиотеку, и ЧТО именно сделать с ними (как использовать хочешь, хотя бы примерный код набросай, а то
чтобы не вставлять теперь везде ^ я хотел сменить указатели переменных на переданные массивы
как-то не совсем понятно для тех, кто НЕ пишет программу вместе с тобой), а потом уже будем говорить, может это FreePascal или нет... <_<
volvo877
незнакомец
 
Сообщения: 8
Зарегистрирован: 04.09.2005 14:34:53

Сообщение Saemon Zixel » 22.04.2006 23:09:47

library test;
var a: array [1..100] as integer;

procedure test(p: pointer); cdecl; export;
begin
@a:=p;
end;

function test2: integer; cdecl; export;
begin
result:=a[1];
end;

exports test;
exports test2;
end.
//-----------------------------------------
program testing;

interface
var
procedure test(p: pointer); external 'libtest.so';
function test2:integer; external 'libtest.so';

t: array [1..100] as integer;
i: integer;

implementation
begin
for i:=1 to 100 do t[i]:=i;
test(@t);
if test2 = 1 then writeln('ok') else writeln('err');
end;

Гдето вот так должно это быть.
Массив создаётся в программе и передаётся только адрес массива.В библеотеке у существующей переменной меняется адресс на 200байт в сегменте данных вызывающей программы, и библеотека делает с этими данными что хочет...
В принципе можно написать export в конце второй строчки и не напрягатся, но у меня появляются проблемы с динамическими массивами.

PS кстати программа при завершении работы выдаёт окошко 'Project raised exception class 'External: SIGSEGV'', а в кансоли
EAccessViolation :
An unhandled exception occurred at $00000000 :
бесконечно. случаем не знаеш из-за чего?
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение zub » 22.04.2006 23:40:50

>>procedure test(p: pointer); cdecl; export;
>>begin
>>@a:=p;
>>end;
:) нет, так не выйдет
>>var a: array [1..100] as integer;
массив создается на стадии компиляции и его адрес ты никак не изменишь
ты определил 2 массива 1 в программе, другой в библиотеке
будет работать чтонить вроде:
library test;
type arr=array [1..100] as integer;
...
function test2(var b:arr): integer; cdecl; export;
begin
result:=b[1];
end;
...
при этом ты неявно передаешь в библиотеку указатель на массив созданый в программе
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Сообщение zub » 22.04.2006 23:51:41

выражение @a:=p; в принципе не должно компилироваться так как @a можно только прочитать, изменить нельзя
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Сообщение Saemon Zixel » 22.04.2006 23:59:05

zub писал(а):library test;
type arr=array [1..100] as integer;
...
function test2(var b:arr): integer; cdecl; export;
begin
result:=b[1];
end;

Да, но когда test2 закончится к b уже нельзя будет достучатся!

Ну хорошо я напишу в начале так

library test;
var
arr: array as integer;
...

и он создастся в куче и будет динамическим, можно будет сменить адрес?

PS Кстати это правда что кача у fpc динамически может растягиватся на всю доступную память компа?
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel » 23.04.2006 00:09:09

zub писал(а):выражение @a:=p; в принципе не должно компилироваться так как @a можно только прочитать, изменить нельзя

Вот из-за подобных вещей мне паскаль и не нравится :(
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение zub » 23.04.2006 00:12:02

Не думай что в других языках такое возможно.
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Сообщение zub » 23.04.2006 00:28:07

>>Да, но когда test2 закончится к b уже нельзя будет достучатся!
можещ сохранить @b в переменной ba:^arr и потом обращаться как ba^[i]...
но так дучше не делать, особенно в библиотеке
>>и он создастся в куче и будет динамическим, можно будет сменить адрес?
что ты подразумеваешь под сменить адрес объекта? я подразумеваю выделить память под объект, скопировать его туда, удалить старый, исправить в программе все ссылки на обект (что невозможно если ты не создаешь объект сам и не хранищь его адрес в переменной через которую к нему и обращаешся)

>>PS Кстати это правда что кача у fpc динамически может растягиватся на всю доступную память компа?
истинная:)
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Сообщение SovNarKom » 23.04.2006 14:40:20

Saemon Zixel
В общем есть такие понятия как передача переменной по ссылке и по значению... вот тебе нужен первый вариант как я понимаю.
То есть тебе нужно передавать в библиотеку указатель на массив

>Да, но когда test2 закончится к b уже нельзя будет достучатся!
А смысл? Этож модульное программирование... Если нужно именно подставлять указатель - работай как делал с ^.
По-другому нельзя никак и нигде.
Единственно - попробовать передавать класс, в котором будет массив.
(но это жутко извратно)

По поводу ошибок - читай про SetMemoryManager (на этом сайте есть).
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Saemon Zixel » 23.04.2006 15:42:51

Спасиба за содержательные ответы. :)
Ситуацию я разрулил дописав export; в библеотеке и external; в программе, получилось как надо.
Но возникла ещё более сложная проблема, не получается воcпользоватся функцией переданой по указателю, вылетает по Access Violution (программа).
Пример:
Код: Выделить всё
library test;
type PGetStr = function (indx: integer): string;
var GetStr: PGetStr; export;

function test(p: pointer; flag: boolean):string; cdecl;
begin
if flag then pointer(GetStr):=p;
result:= GetStr(1);
end;
exports test;
end.
//-------------------------------
program testing;

interface
type PGetStr = function (indx: integer): string;
var ExGetStr: PGetStr; external name 'GetStr';
function test(p: pointer; flag: boolean):string; cdecl; external 'libtest.so';

implementation
{$F+}
function GetStr(indx: integer): string;
begin
  result:=IntToStr(indx);
end;
{$F-}

begin
writeln(test(@GetStr,true));
//или так
ExGetStr:=@GetStr;
writeln(test(nil,false));
end.

Никак не пойму, как правельно cделать. :(
PS Из летературы есть только учебник по TP5.5 :unsure:
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение zub » 23.04.2006 17:00:38

Стринги нельзя передавать из dll в ехе или что там в линуксе. переменная типа string - динамический массив, должен убиваться или изменяться в томже модуле где создан.
Чето ты какието сложности наводишь на пустом месте:) скажи конкретно что ты хочешь получить?
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Сообщение Saemon Zixel » 23.04.2006 21:48:29

После отката на fpc2.0.0 и Lazarus 0.9.12 вариант с ExGetStr:=@GetStr заработал нормально :) .
Но теперь я зашол в полный тупик :( .

Стринги нельзя передавать из dll в ехе или что там в линуксе. переменная типа string - динамический массив, должен убиваться или изменяться в томже модуле где создан.

Ну хорошо поставлю я string[256]; не в этом дело.

Чето ты какието сложности наводишь на пустом месте скажи конкретно что ты хочешь получить? 

Я хотел чтоб библеотека, когда ей понадобится, вызываля функцию в программе с запросом нужной строки.
Примерно...
Код: Выделить всё
library test;
type PGetStr = function (indx: integer): string;
var GetStr: PGetStr; export;

procedure test; cdecl;
var i: integer;
begin
  for i:= 1 to 22 do writeln(GetStr(i));
end;

exports test;
end.
//-------------------------------
program testing;
uses Classes;
interface
type
PGetStr = function (indx: integer): string;
var
ExGetStr: PGetStr; external name 'GetStr';
FileWithStrings: TStringList;

implementation
function GetStr(indx: integer): string;
begin
 result:=FileWithString.Strings[indx];
end;

begin
 FileWithStrings:=TStringLisr.Create;
 FileWithStrings.LoadFromFile('testing.pas');
 ExGetStr:=@GetStr;
 test;
 FileWithStrings.Free;
end.


Всё так хорошо было, а теперь оказалось что вызываемая библеотекой функция GetStr в программе выполняется в контексте библеотеки и о FileWithStrings обьекте ничего не знает :( . После долгих раздумий (~2часа) и поиска в гугле (~3 часа) я понял что если неполучится менять контекст на программный при вызове, то придётся переробатывать много строчек кода в библеотеке и менять логику многих функций <_< , а это очень плохо.

PS Вот-так меня кинул этот fp <_<
PSS Кстати откапал какойто термин - "callback", он может отнасится к моей проблеме?
Saemon Zixel
новенький
 
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

След.

Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru