Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.05.30;
Скачать: [xml.tar.bz2];

Вниз

Использование 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 вся ветка

Форум: "Основная";
Текущий архив: 2004.05.30;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.038 c
14-1084382180
NailMan
2004-05-12 21:16
2004.05.30
Че-то запутался с приведением к типу... :-(


14-1084460862
Анонимщик
2004-05-13 19:07
2004.05.30
BoundsChecker


14-1083988921
mfender
2004-05-08 08:02
2004.05.30
Безумцы!


7-1081885251
KyRo
2004-04-13 23:40
2004.05.30
Как добится что бы программа работала на нескольких ОС


1-1085037983
MegaVolt
2004-05-20 11:26
2004.05.30
Как правильно обработать ошибку внутри класса?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский