我現(xiàn)在正在寫一個DLL,看書上說最好不要使用STRING,應該用PCHAR,所以我把所有STRING類型的數(shù)據(jù)改為PCHAR型了,但是新的問題出現(xiàn)了,有些DELPHI的函數(shù)是要用到STRING的,如
var
a : pchar
begin
setlength(a,64);
delete(a,1,5);
end;
這兩個函數(shù)都分別報出了錯誤,請問該如何解決呢?
end
--------------------------------------------------------------------------------
function TForm1.PcharSplit(In_Str_NeedSplit:Pchar;Var Out_Arr_Splited:Array of Pchar):Boolean ;
Var
Pv_Int_postion,pv_Int_Rows : integer;
Pv_Str_NeedSplit : String;
BEGIN
Try
Result:=True;
Pv_Str_NeedSplit := In_Str_NeedSplit;
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit) ;
if Pv_Int_postion =1 then
begin
delete(Pv_Str_NeedSplit, 1,Pv_Int_postion );
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit);
end;
pv_Int_Rows:=0;
while ( Pv_Int_postion > 0 ) do
begin
Out_Arr_Splited[pv_Int_Rows] := Pchar(copy(Pv_Str_NeedSplit, 1, Pv_Int_postion - 1));
delete(Pv_Str_NeedSplit,1,Pv_Int_postion);
//showmessage(Out_Arr_Splited[pv_Int_Rows]);
pv_Int_Rows := pv_Int_Rows + 1;
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit);
end ;
Except
Result := False;
exit;
end;
end ;
大家看看,這個函數(shù)我已經(jīng)發(fā)上來了,為什么我調用的時候是空植呢?
--------------------------------------------------------------------------------
var
a : pchar
begin
setlength(string(a),64);
delete(string(a),1,5);
end;
--------------------------------------------------------------------------------
可以用string的,只不過,這樣的dll只能用delphi來調用了。
如果要做到通用呢,才需要用pchar
--------------------------------------------------------------------------------
如果你的DLL只是自己用的話可以用string的,
在Uses的最前面加上 ShareMem 就可以了。
--------------------------------------------------------------------------------
謝謝樓上的各位,但是我寫的DLL是要給PB或者其他應用程序調用的,所以必須通用啊,有沒有什么辦法解決???
1樓的兄弟,這樣做,還是用到了STRING類型啊,其他調用也是出錯的
--------------------------------------------------------------------------------
DLL里面是可以用String,只要傳遞的參數(shù)不是String就不用擔心。參數(shù)可以用PChar,函數(shù)內部再轉換
--------------------------------------------------------------------------------
如果你的字符串長度不超過 255,完全可以用 ShortString,用法同 String,并且可以用在 Dll 中:
var
a: ShortString;
begin
SetLength(a, 64);
Delete(a, 1, 5);
end;
--------------------------------------------------------------------------------
// delete(In_Str_NeedSplit, 1,Pv_Int_postion );
MoveMemory(Pchar(In_Str_NeedSplit),Pchar(length(In_Str_NeedSplit))+Pv_Int_postion,length(In_Str_NeedSplit)-Pv_Int_postion-1);
哪位大哥幫我看看,這樣的轉化為什么出錯呢?
--------------------------------------------------------------------------------
我記得好像是在傳參數(shù)時要用pchar,內部可用string吧,你在內部轉換一下就好了
--------------------------------------------------------------------------------
1、同志哥,你這都寫些什么???看看 MoveMemory 的聲明:
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
第一個參數(shù)是目的地址,第二個參數(shù)是源地址,你把字符串的長度移到字符串里干什么??
2、另外 In_Str_NeedSplit、Pv_Int_postion 這兩個變量是什么類型、干什么的,你準備實現(xiàn)什么功能,請說清楚,我們沒時間跟你猜啞謎。
--------------------------------------------------------------------------------
呵呵,不好意思
1.delete(In_Str_NeedSplit, 1,Pv_Int_postion )
in_str_needsplit:Pchar類型:傳入的字符串;
Pv_int_postion:integer類型:傳入的字符串的起始位置;
做個例子:我傳入的是|A|B|,經(jīng)過delete后就是 A|B|
2.另外有個問題:
我定義了一個函數(shù)function test(Var a :Array of Pchar):boolean;
我這樣調用它:
procedure testf;
var
b : array of Pchar;
begin
setlength(b,10);
test(b);
showmessage(b[1]);
end;
可以確定我函數(shù)沒有錯,輸出的數(shù)據(jù)在函數(shù)內部可以看到結果,為什么我調用的時候卻得到空的結果?
--------------------------------------------------------------------------------
DLL 里可以用String 呀
只是在接口部分別用string就行了
--------------------------------------------------------------------------------
加入sharemem
這個單元試試
--------------------------------------------------------------------------------
1、你寫的函數(shù)不能用,因為動態(tài)數(shù)組不能作為參數(shù)在 dll 中傳遞。給你寫了一個,Out_Count 返回分割的字符串數(shù),函數(shù)返回字符串地址列表在內存中的地址。
function PCharSplit(const In_Str_NeedSplit: PChar; var Out_Count: Longint): PPChar;
var
hMem: LongWord;
p: PChar;
flag: LongBool;
head: array[0..65535] of PChar;
pp: PPChar;
i: Longint;
begin
hMem := GlobalAlloc(GMEM_MOVEABLE, StrLen(In_Str_NeedSplit) + 1);
p := GlobalLock(hMem);
StrCopy(p, In_Str_NeedSplit);
GlobalUnlock(hMem);
flag := False;
Out_Count := 0;
while p^ <> #0 do
begin
if p^ = ‘|‘ then
begin
p^ := #0;
if flag then flag := False;
end
else if not flag then
begin
head[Out_Count] := p;
Inc(Out_Count);
flag := True;
end;
Inc(p);
end;
hMem := GlobalAlloc(GMEM_MOVEABLE, Out_Count * SizeOf(PChar));
Result := GlobalLock(hMem);
pp := Result;
i := 0;
while i < Out_Count do
begin
pp^ := head[i];
Inc(pp);
Inc(i);
end;
GlobalUnlock(hMem);
end;
2、這個函數(shù)這么使用
var
s: PChar;
pp: PPChar;
count, i: Integer;
begin
s := ‘|ab|cd|e|fghi|‘;
pp := PCharSplit(s, count);
for i := 0 to count - 1 do
begin
ShowMessage(pp^);
Inc(pp, 1);
end;
end;
--------------------------------------------------------------------------------
謝謝這位兄弟,這個函數(shù)好象復雜了點,:)
再問一下,如果我這個函數(shù)是在DLL中的各個單元之間調用的,可以用Array of String 嗎?如果可以,就不用那么費勁了,因為我這個函數(shù)不給外界用的。
--------------------------------------------------------------------------------
如果用STRING類型改為WideString類型就可以了。
--------------------------------------------------------------------------------
to bbscom:
你 試過 沒有的?。课液孟裨囘^不行。:)
to plenilune168 ,
“DLL里面是可以用String,只要傳遞的參數(shù)不是String就不用擔心。參數(shù)可以用PChar,函數(shù)內部再轉換”,您確定這樣能行的嗎?因為我是第一次做DLL:)
謝謝?。?!
--------------------------------------------------------------------------------
“DLL里面是可以用String,只要傳遞的參數(shù)不是String就不用擔心。參數(shù)可以用PChar,函數(shù)內部再轉換”是沒有問題的
如果出錯就是你函數(shù)內部程序的問題
--------------------------------------------------------------------------------
to plenilune168:
謝謝了,再問一下,
如果我這個函數(shù)是在DLL中的各個單元之間調用的,可以用String 嗎?因為我這個函數(shù)不給外界用的。
--------------------------------------------------------------------------------
內部之間沒影響
--------------------------------------------------------------------------------
to:plenilune168 非常感謝了,再問問你:
function TForm1.PcharSplit(In_Str_NeedSplit:Pchar;Var Out_Arr_Splited:Array of Pchar):Boolean ;
Var
Pv_Int_postion,pv_Int_Rows : integer;
Pv_Str_NeedSplit : String;
BEGIN
Try
Result:=True;
Pv_Str_NeedSplit := In_Str_NeedSplit;
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit) ;
if Pv_Int_postion =1 then
begin
delete(Pv_Str_NeedSplit, 1,Pv_Int_postion );
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit);
end;
pv_Int_Rows:=0;
while ( Pv_Int_postion > 0 ) do
begin
Out_Arr_Splited[pv_Int_Rows] := Pchar(copy(Pv_Str_NeedSplit, 1, Pv_Int_postion - 1));
delete(Pv_Str_NeedSplit,1,Pv_Int_postion);
//showmessage(Out_Arr_Splited[pv_Int_Rows]);
pv_Int_Rows := pv_Int_Rows + 1;
Pv_Int_postion := pos(‘|‘,Pv_Str_NeedSplit);
end ;
Except
Result := False;
exit;
end;
end ;
為什么我調用的時候是空植呢?
我這樣調用它:
procedure testf;
var
b : array of Pchar;
begin
setlength(b,10);
test(b);
showmessage(b[1]);
end;
--------------------------------------------------------------------------------
把完整的代碼貼出來吧,包括DLL工程和調用的工程,不然讓我們猜我們可沒有這個本事。
--------------------------------------------------------------------------------
對dll,導入,導出用PChar就可以了,里面可以用string的.再說string到pchar也比較簡單的.
--------------------------------------------------------------------------------
to:plenilune168
“PcharSplit”這個函數(shù)我在applation里運行的,不用DLL;在button單擊事件中調用這個函數(shù)(PcharSplit)時返回值和預期的結果不同
procedure button.click();
var
b : array of Pchar;
begin
setlength(b,10);
PcharSplit(‘|1|2|3|‘,b);
showmessage(b[1]);
end
預期結果應該是1,但是得出的是空值,為什么呢?
--------------------------------------------------------------------------------
我試過用array of pchar是得不到預期結果的,可能是和指針有關系,具體我也搞不清楚,如果只是內部調用改為string算了
--------------------------------------------------------------------------------
To 樓主:
1、動態(tài)數(shù)組和 string 類型是不能作為 dll 函數(shù)的參數(shù)和返回值的。另外老兄,我一般不寫“麻煩”的代碼,你仔細看看再下結論。我的目的是掃描一次字符串,將凡是“|”的地方都變?yōu)?0,同時記錄被分割字符串的第一個字符的位置:|ab|cd|e|fghi|——>#0ab#0cd#0e#0fghi#0,取字符串的時候自然在 #0 處截斷。
2、你的程序為什么得不到東西,原因很簡單:
“Out_Arr_Splited[pv_Int_Rows] := PChar(Copy(Pv_Str_NeedSplit......)”這句有問題:
他相當于
var s: string;
s := Copy(Pv_Str_NeedSplit, 1......);
Out_Arr_Splited[pv_Int_Rows] := PChar(s);
一個臨時變量在函數(shù)生存期后就會被回收,你光把他的地址保存起來,能得到什么??
3、另外你的這個函數(shù)是有缺陷的,連續(xù)的“|”(如“|1||||2|3|”)就歇菜了。
4、我就知道這些了,你嫌麻煩問其他人吧。
--------------------------------------------------------------------------------
to :vvyang
謝謝了,請問你可以把你的方法用代碼實現(xiàn)出來嗎,讓我參考一下
--------------------------------------------------------------------------------
vvyang上面給出的難道是外星文字,不是代碼?你仔細看沒有啊?
--------------------------------------------------------------------------------
To skywater007:
7 樓、15 樓還有 27 樓的那個家伙都是我,所以,算上這次我一共回復了 4 遍。
代碼、程序錯誤及其原因都解釋的很清楚,別的無話可說。
--------------------------------------------------------------------------------
用FastMM吧,不用DLL也可以實現(xiàn)DLL和EXE傳遞字符串了,下載網(wǎng)址
http://fastmm.sourceforge.net/
Dephi 2006里的內存管理器已經(jīng)是 FastMM 了
--------------------------------------------------------------------------------
to Lingsg兄
我也聽說2006里面就是fastmm了,可是為什么用2006創(chuàng)建dll的時候,還是提示帶上sharemem呢?我找了下,Source里面沒FastMM這樣的單元。請指教。
--------------------------------------------------------------------------------
Delphi 2006幫助
Shared-Memory Manager (Win32 Only)
On Win32, if a DLL exports routines that pass long strings or dynamic arrays
as parameters or function results(whether directly or nested in records or
objects), then the DLL and its client applications (or DLLs) must all use the
ShareMem unit. The same is true if one application or DLL allocates memory
with New or GetMem which is
deallocated by a call to Dispose or FreeMem in another module. ShareMem should
always be the first unit listed in
any program or library uses clause where it occurs.
ShareMem is the interface unit for the BORLANDMM.DLL memory manager, which allows modules to share
dynamically allocated memory. BORLANDMM.DLL must be deployed with applications and DLLs that use ShareMem. When an application or DLL uses ShareMem, its
memory manager is replaced by the memory manager in BORLANDMM.DLL.
--------------------------------------------------------------------------------
To: zqw0117
開始我也覺得迷惑,后來打開 GetMem.inc 一看就什么都明白了:)(里面的代碼就是FastMM,作者就是:Pierre le Riche)
至于怎么用可以看Delphi自帶例子:
Demos\DelphiWin32\VCLWin32\MemMgr\SimpleShareMem
在主程序和DLL的項目引用第一行加上: SimpleShareMem, 就可以了