Вниз
Скачать: CL | DM;

Использование PChar в dll   Найти похожие ветки 

← →
Lammo   (2004-05-16 19:15) [0]

как правильно?

function Test(c: PChar): PChar;
var
 s: String;

begin
s := StrPas(c); // либо просто s := c  ?
s := s+"!";

Result := PChar(s);
end;

procedure TForm.ButtonClick(Sender: TObject);
var
 str : String;

begin
str := "123";
ShowMessage(Test(PChar(str)));
end;


такой код правильный?


← →
MaxDDinc   (2004-05-16 19:20) [1]

Процедура ShowMessage работает с типом STRING, а Ваша функция возвращает PChar ... а преобразовать в STRING можно через String(pMyChar: pChar)


← →
Rouse_ ©   (2004-05-16 19:20) [2]

Используй ShortString, огребешь меньше проблем...


← →
Lammo   (2004-05-16 19:26) [3]


> Rouse_ ©   (16.05.04 19:20) [2]

А если его длинны недостаточно?


← →
Polevi ©   (2004-05-16 19:28) [4]

COM сервер и WideString


← →
Lammo   (2004-05-16 19:33) [5]


> Polevi ©   (16.05.04 19:28) [4]

Это уже слишком далеко.....

я просто спросил код правильный?


← →
Polevi ©   (2004-05-16 19:39) [6]

мне не нравится


← →
Lammo   (2004-05-16 19:43) [7]

а как тогда?


← →
Гаврила ©   (2004-05-16 19:44) [8]

WideString(COM не обязательно)


> такой код правильный?


не правильный в корне
вылетишь с ошибкой "неверный указатель", причем не сразу, а через некоторое время, искать ошибку замучаешься


← →
Lammo   (2004-05-16 19:54) [9]

function Test(c: PChar): PChar;
var
s: String;
h: PChar;

begin
s := StrPas(c);
s := s+"!";
h := PChar(s);

Result := @h^;
end;

так тоже нельзя?


← →
Гаврила ©   (2004-05-16 20:16) [10]

так тоже нельзя

локальная переменная s освобождается при выходе за область видимости, то есть при выходе из функции test.
ТОчнее освобождается память, на которую переменная указывает.
Таким образом, результатом функции будет указатель на уже освобожденную память


← →
Lammo   (2004-05-16 20:22) [11]

тогда как сделать что б было все ок?


← →
Гаврила ©   (2004-05-16 20:44) [12]

А что ты хочешь сделать ?
если функция сделана только
для добавления "!" к строке, используй widestring как результат и как параметр.
Неоптимально с точки зрения управленя ресурсами и быстродействием, зато оптимально с точки зрения скорости программирования


← →
Lammo   (2004-05-16 21:02) [13]

Я пишу dll, и в качестве параметров мне нужно передавать строки…
Я просто хочу знать как правильно использовать PChar в таких случаях. Можно пример пожалуйста?


← →
Гаврила ©   (2004-05-16 21:10) [14]


> Lammo   (16.05.04 21:02) [13]

при работе с PChar важно помнить, кто выделяет память, а кто ее освобождает. Если при этом еще и ведется работа с разными модулями (dll и Exe - это модули), то ситуация несколько усложняется тем, что работают разные менеджеры памяти, для каждого модуля свой.
Общее правило - кто выделил память, то ее и освобождает.
Следовательно, выделять память в данном случае возможно должен exe, и передавать параметром процедуры в dll указатель на уже выделенный кусок памяти. Так работает большинство (если не все) функций API


← →
Lammo   (2004-05-16 22:32) [15]

Можно пример пожалуйста, уже целый день сижу все никак не могу разобраться.


← →
Rouse_ ©   (2004-05-16 23:19) [16]

Может быть приведешь задачу более полно, так как именно в данном варианте я бы отказался от PChar и использовал несколько другой механизм...


← →
jack128 ©   (2004-05-16 23:45) [17]

классический вариант, как это делаю я :-)

function Test(InputStr, OutputStr: PChar; MaxLength: Cardinal): LongInt;
var
 s: String;
begin
 s := InputStr;
 s := s+"!";
...
 if (Length(s) + 1) > MaxLength then
   Result := 0
 else
 begin
   Move(PChar(s)^, OutputStr^, Length(s));
   OutputStr[Length(s) + 1] := #0;
 end;
end;

procedure TForm.ButtonClick(Sender: TObject);
var
 str : String;
 str2: string;
begin
 SetLength(str2, 1000);
 str := "123";
 SetLength(str2, Test(PChar(str), str2, Length(str2)));
 ShowMessage(str2);
end;


← →
Polevi ©   (2004-05-17 10:39) [18]

type
 TTest = class(TAutoObject, ITest)
 protected
   function Test(const Str: WideString): WideString; safecall;
   { Protected declarations }
 end;

implementation

uses ComServ;

function TTest.Test(const Str: WideString): WideString;
begin
 Result:=Str+"!";
end;

procedure TForm.ButtonClick(Sender: TObject);
var
 z:OleVariant;
begin
 z:=CreateOleObject("Srv.Test");
 ShowMessage(z.Test("123"));
wMessage(str2);
end;


← →
Lammo   (2004-05-17 18:12) [19]

Спасибо.

ок, а внутри dll, можно использовать тип String?
и еще, в качестве параметров string с фиксированной длинной (string[20])?


> jack128 ©   (16.05.04 23:45) [17]

код работать не будет...


← →
Lammo   (2004-05-17 18:39) [20]


> Rouse_ ©   (16.05.04 23:19) [16]

Мне не нужны никакие «левые» способы реализации задачи…
Есть главный модуль и dll, внутри их все функции работают с типом String, я хочу знать каким образом можно передавать строки в качестве параметров, между главным модулем и dll, используя PChar.
Уже весь хелп перечитал, что-то все никак не доходит до меня…


← →
panov ©   (2004-05-17 18:48) [21]

>Lammo

Самый простой способ решить проблемы в случае, если планируется использование DLL только при разработке в Delphi - использовать один менеджер памяти в Applicatino и в DLL:

uses ShareMem,... и в DLL и в файле проекта.


← →
Lammo   (2004-05-17 19:22) [22]


> panov ©   (17.05.04 18:48) [21]

Я не думаю, что я буду использовать библиотеки написанные на других языках, но само условие, что их нельзя будет использовать в таком случае, меня не устраивает…

не отходите пожалуйста от темы, я ХОЧУ ИСПОЛЬЗОВАТЬ PCHAR! Зачем искать другие пути, я хочу научится.
Можете дать реально работающий пример, или ссылку где все нормально написано?


← →
Lammo   (2004-05-17 19:23) [23]


> Lammo   (17.05.04 18:12) [19]


← →
jack128 ©   (2004-05-17 20:55) [24]


> код работать не будет...
проясни?


← →
Fredericco ©   (2004-05-17 20:59) [25]

function GetCoolPChar(StringIn: Pchar): Pchar ;
var
  lpGlobalMemory: pointer ;
begin
   lpGlobalMemory:=nil;
  hGlobalMemory := GlobalReAlloc(hGlobalMemory,strlen(StringIn)+1, GMEM_MOVEABLE);
  if hGlobalMemory <> 0 then { memory allocated OK }
     begin
       lpGlobalMemory := GlobalLock(hGlobalMemory);
       lstrcpy(lpGlobalMemory,StringIn);
       GlobalUnlock(hGlobalMemory);
     end;
  Result:= Pchar(lpGlobalMemory);
end;

В DLL:
function Test(c: PChar): PChar;
var
s: String;

begin
s := StrPas(c); // либо просто s := c  ?
s := s+"!";

Result := GetCoolPChar(PChar(s));
end;

Не забудь в Initialization DLL сделать вот это:
 hGlobalMemory := GlobalAlloc(GMEM_MOVEABLE , 1);


← →
Lammo   (2004-05-17 21:17) [26]


> Fredericco ©   (17.05.04 20:59) [25

Спасибо.
А вроде ж можно как-то попроще, или нет?


← →
Fredericco ©   (2004-05-17 21:31) [27]

Это самое простое, хоть и не правильное.
А что б правильно было см. Гаврила ©   (16.05.04 21:10) [14]


← →
Lammo   (2004-05-17 21:35) [28]

Блин, неужели все так тяжело?

Мастера, дайте пожалуйста правильный работающий код и, если можно, ссылку где про это все написано.
Заранее благодарен!


← →
Fredericco ©   (2004-05-17 22:16) [29]

Вот ты неугомонный :-)
Есть ЕХЕ (Е) и ДЛЛ (Д). Ты из Е вызываешь функцию из Д. Хочешь получить обратно в Е результат. PChar это ссылка на область памяти. Кто эту память должен выделить? Микрософт считает что Е см. [14]. А ты как думаешь? В [25] пример, когда память выделается в Д, но это не правильно. Хорошо, простой способ. Ты его сам в своем первом посте привел. Там тоже, ессно, идет выделение памяти. Под переменную s:string. Эту память выделит и потом !обязательно! освободит Дельфи. Память помечается как свободная, то есть область памяти выделенная под результат твоей функции может быть еще не потерта, а может быть и потерта. Вероятность последнего, по моему опыту, ~40%. Как тут проще?

ЗЫ. Разве это сложно?


← →
evvcom ©   (2004-05-18 00:22) [30]


> Блин, неужели все так тяжело?

Если подумать, то здесь все просто. Обрати еще раз внимание на
> Кто эту память должен выделить? Микрософт считает что Е
> см. [14].

Посмотри, как функции API сделаны. Например,

function GetWindowText(hWnd: HWND; lpString: PChar; nMaxCount: Integer): Integer; stdcall;

В своем exe выделяешь память, не используя менеджер памяти Дельфи, например, lpString := HeapAlloc(..., ..., nMaxCount); И спокойно потом вызываешь GetWindowText с параметром PChar. И работать будет потом с чем угодно. Да, память освобождать тоже надо будет потом в exe: HeapFree(..., ..., lpString);



Страницы: 1 вся ветка

Скачать: CL | DM;



Память: 0.52 MB
Время: 0.024 c
14-1084038401
проходил мимо
2004-05-08 21:46
2004.05.30
Delphi 8


7-1082541474
-=Uncle Bob=-
2004-04-21 13:57
2004.05.30
обработка клавиш


6-1081446290
Сергей Ю.
2004-04-08 21:44
2004.05.30
Win98 и XP


11-1072555653
Юрий Ж.
2003-12-27 23:07
2004.05.30
Thread?


14-1084024608
default
2004-05-08 17:56
2004.05.30
ImageHlp.h




   Наверх