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

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

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

Saemon Zixel
новенький
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel »

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

var
a: integer;
b: integer;

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

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

Какими путями надо пойти чтоб a и b были именами одной ячейки памяти?
Может ли freepascal своими расширениями подобное осуществить?
virt
новенький
Сообщения: 35
Зарегистрирован: 01.12.2005 11:31:41

Сообщение virt »

Код: Выделить всё

var a : integer;
    b : integer absolute a;

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


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

Сообщение Saemon Zixel »

Про absalute я уже знаю.
Просто я пишу библеотеку, каторая использует несколько массивов, а массивы создаёт и заполняет программа использующую эту библеотеку.
И чтобы не вставлять теперь везде ^ я хотел сменить указатели переменных на переданные массивы.
Но видать такое freepascal не умеет. жалль <_<
volvo877
незнакомец
Сообщения: 8
Зарегистрирован: 04.09.2005 14:34:53

Сообщение volvo877 »

Saemon Zixel,
напиши, КАК ты хочешь передавать параметры в библиотеку, и ЧТО именно сделать с ними (как использовать хочешь, хотя бы примерный код набросай, а то
чтобы не вставлять теперь везде ^ я хотел сменить указатели переменных на переданные массивы
как-то не совсем понятно для тех, кто НЕ пишет программу вместе с тобой), а потом уже будем говорить, может это FreePascal или нет... <_<
Saemon Zixel
новенький
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel »

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 :
бесконечно. случаем не знаеш из-за чего?
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>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
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

выражение @a:=p; в принципе не должно компилироваться так как @a можно только прочитать, изменить нельзя
Saemon Zixel
новенький
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel »

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 »

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

Вот из-за подобных вещей мне паскаль и не нравится :(
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

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

Сообщение zub »

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

>>PS Кстати это правда что кача у fpc динамически может растягиватся на всю доступную память компа?
истинная:)
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

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

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

По поводу ошибок - читай про SetMemoryManager (на этом сайте есть).
Saemon Zixel
новенький
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel »

Спасиба за содержательные ответы. :)
Ситуацию я разрулил дописав 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:
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Стринги нельзя передавать из dll в ехе или что там в линуксе. переменная типа string - динамический массив, должен убиваться или изменяться в томже модуле где создан.
Чето ты какието сложности наводишь на пустом месте:) скажи конкретно что ты хочешь получить?
Saemon Zixel
новенький
Сообщения: 78
Зарегистрирован: 20.09.2005 18:19:54
Откуда: Sochi

Сообщение Saemon Zixel »

После отката на 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", он может отнасится к моей проблеме?
Ответить