全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3870
推到 Plurk!
推到 Facebook!

DLL函数返回PCHAR值问题

答題得分者是:wyndog
cxg
中階會員


發表:116
回覆:192
積分:76
註冊:2004-02-12

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-09-30 09:40:35 IP:222.35.xxx.xxx 未訂閱
我在DLL中定义了一个串口通讯的函数,然后在调用时返回值老是不正确,不知道为什么,但我改成STRING,然后用SHAREMEM就没有问题,但是这样用非DELPHI好像不能调用吧,所以我想改成PCHAR。下面是我的DLL的代码,麻烦各位大虾帮我检查一下。 library DRYPRT5; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses SysUtils, Classes, PRTTING in 'PRTTING.pas'; {$R *.RES} EXPORTS OPEN_PORT, CLOSE_PORT, SEND_COMMAND; begin end. //============================================ unit PRTTING; interface USES Windows, Forms, ExtCtrls, SysUtils, SPComm; TYPE TMYOBJ = CLASS PROCEDURE MYComReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word); END; VAR WAIT_TIMES, N_NUMBER : INTEGER; START_TIMES : REAL; READ_BUSY, OPEN_BUSY, PORT_ACTIVE, RECEIVE_FINISH : BOOLEAN; S_DATA : STRING; MYCOM : TCOMM; MYOBJ : TMYOBJ; FUNCTION OPEN_PORT( PORT : SHORTSTRING; BTL : INTEGER) : INTEGER;STDCALL; FUNCTION CLOSE_PORT : INTEGER;STDCALL; FUNCTION SEND_COMMAND( SD : STRING; VAR RD : PChar) : INTEGER;STDCALL; implementation PROCEDURE INI_OBJ; begin MYOBJ := TMYOBJ.Create; MYCOM := TComm.Create( NIL); MYCOM. MYOBJ.MYComReceiveData; end; PROCEDURE FREE_OBJ; BEGIN TRY IF MYOBJ<>NIL THEN BEGIN MYOBJ.FREE; MYOBJ := NIL; END; IF MYCOM<>NIL THEN BEGIN MYCOM.FREE; MYCOM := NIL; END; EXCEPT END; END; PROCEDURE TMYOBJ.MYComReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word); VAR S1 : STRING; BEGIN START_TIMES := NOW; SetLength( S1, BufferLength); MOVE( Buffer^, PCHAR(S1)^, BufferLength); S_DATA := S_DATA S1; IF POS( #13, S_DATA)>0 THEN RECEIVE_FINISH := TRUE; END; FUNCTION SEND_COMMAND( SD : STRING; VAR RD : PChar) : INTEGER;STDCALL; VAR N2 : REAL; B : BOOLEAN; BEGIN IF READ_BUSY THEN BEGIN RESULT := 0; EXIT; END; IF NOT PORT_ACTIVE THEN BEGIN RESULT := -1; EXIT; END; READ_BUSY := TRUE; RECEIVE_FINISH := FALSE; START_TIMES := NOW; S_DATA := ''; MYCOM.WriteCommData( SD); B := FALSE; WHILE NOT RECEIVE_FINISH DO BEGIN APPLICATION.ProcessMessages; N2 := NOW - START_TIMES; N2 := N2 * 100000000; B := N2 > 2000; IF B THEN BREAK; END; IF B THEN RESULT := -2 // 超时没有返回值 ELSE RESULT := 1; RD := PCHAR( S_DATA); S_DATA := ''; READ_BUSY := FALSE; END; FUNCTION OPEN_PORT( PORT : SHORTSTRING; BTL : INTEGER) : INTEGER;STDCALL; BEGIN IF OPEN_BUSY OR READ_BUSY THEN BEGIN RESULT := 0; EXIT; END; IF PORT_ACTIVE THEN BEGIN RESULT := -1; EXIT; END; OPEN_BUSY := TRUE; INI_OBJ; MYCOM.BaudRate := BTL; MYCOM.CommName := PORT; TRY MYCOM.StartComm; PORT_ACTIVE := TRUE; RESULT := 1; EXCEPT PORT_ACTIVE := FALSE; RESULT := -2; END; OPEN_BUSY := FALSE; END; FUNCTION CLOSE_PORT : INTEGER;STDCALL; BEGIN TRY IF MYCOM<>NIL THEN MYCOM.StopComm; PORT_ACTIVE := FALSE; RESULT := 1; EXCEPT RESULT := -1; END; FREE_OBJ; END; end.
wyndog
資深會員


發表:7
回覆:362
積分:348
註冊:2004-10-12

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-09-30 11:11:38 IP:60.248.xxx.xxx 未訂閱
FUNCTION SEND_COMMAND( SD : STRING; VAR RD : PChar) : INTEGER;STDCALL; 改成 FUNCTION SEND_COMMAND(SD, RD: PChar): INTEGER; STDCALL; 不要用 VAR DLL 中的函數的參數,一律不要用 string 跟 動態陣列 這樣才能放給其它程式語言使用
cxg
中階會員


發表:116
回覆:192
積分:76
註冊:2004-02-12

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-09-30 13:23:57 IP:222.35.xxx.xxx 未訂閱
谢谢reptile,但我还想问一下,如果不用 var 那怎么返回RD中的内容呢?
wyndog
資深會員


發表:7
回覆:362
積分:348
註冊:2004-10-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-09-30 13:37:12 IP:60.248.xxx.xxx 未訂閱
你的 RD 是需要傳回來的 所以,如果考慮到記憶體分配的問題 最好是在呼叫端配置比較好 也就是說,在呼叫 SEND_COMMAND 前先配好記憶體 所以在 Delphi 裡,要變這樣 SetLength(RD, 256); // 分配好適度的空間 SEND_COMMAND(PChar(SD), PChar(RD)); 再來就是,SEND_COMMAND 裡,要把 RD := PChar(S_DATA); 這段改掉 改成 Move(S_DATA[1], RD^, length(S_DATA)); 把 S_DATA 複製到 RD 去,而不要讓 RD 直接傳回 Pointer
cxg
中階會員


發表:116
回覆:192
積分:76
註冊:2004-02-12

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-09-30 13:56:36 IP:222.35.xxx.xxx 未訂閱
Move(S_DATA[1], RD^, length(S_DATA)); 我用 RD := StrNew( PCHAR( S_DATA)); 代替有问题吗? 非常感谢!
wyndog
資深會員


發表:7
回覆:362
積分:348
註冊:2004-10-12

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-09-30 14:35:36 IP:60.248.xxx.xxx 未訂閱
我沒這樣寫過,不過,看起來可行,就試試看吧
cxg
中階會員


發表:116
回覆:192
積分:76
註冊:2004-02-12

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-10-02 12:50:57 IP:222.35.xxx.xxx 未訂閱
引言: 我沒這樣寫過,不過,看起來可行,就試試看吧
谢谢reptile。
系統時間:2017-12-18 7:28:46
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!