在DLL中使用PCHAR作为参数传递的问题(200分)

  • 主题发起人 主题发起人 RJU
  • 开始时间 开始时间
R

RJU

Unregistered / Unconfirmed
GUEST, unregistred user!
看了很多关于这方面的问题,仍然不得其解<br>在DLL中使用PCHAR作为参数的奇怪问题<br><br>有如下的测试程序(没有加入SHAREMEM单元),在DLL中有一个函数<br>&nbsp;Function GetUserName(userid:Pchar;var vName:PChar):boolean;<br>&nbsp;begin<br>&nbsp; &nbsp; SHOWMESSAGE(USERID);//在此跟踪,得到的USERID经常是乱码<br>&nbsp;end;<br><br>&nbsp;在多次尝试中,得到下面的程序是能正常运行,但感觉无法保证程序得稳定性.问题如下<br>&nbsp; 1:能否解释 注释部分出现的现象是什么原因?<br>&nbsp; 2:对在DLL中传递字符串常量和返回字符串有什么好的建议<br>&nbsp; 3:对在DLL中传递一个自定义类型的数据有什么好的方法?<br><br>&nbsp;var<br>&nbsp; &nbsp;GetuserName:TMgetuserName;<br>&nbsp; &nbsp;DllPathFile,temp: String;<br>&nbsp; &nbsp;cHnd: THandle;<br>&nbsp; &nbsp;userid,vName:Pchar;<br>&nbsp;begin<br>&nbsp; cHnd:=0;<br>&nbsp; DllPathFile :=Trim('my.dll');<br>&nbsp; if NOT FileExists(DllPathFile) Then<br>&nbsp; &nbsp; &nbsp;Exit;<br>&nbsp; GetMem(vName,255);<br>&nbsp; Try<br>&nbsp; &nbsp; &nbsp;strPCopy(vName,'00');<br>&nbsp; &nbsp; &nbsp;cHnd :=LoadLibrary(PChar(DllPathFile));<br>&nbsp; &nbsp; &nbsp;if cHnd&gt;0 then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; MgetuserName:=GetProcAddress(cHnd,'MgetuserName');<br>&nbsp; &nbsp; &nbsp; &nbsp; temp:='291';<br>&nbsp; &nbsp; &nbsp; &nbsp; UserID:=PChar(temp); // 只有这样赋值,参数才能正确传递,如果用 &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// GetMem,setPCopy的方法,传递的<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// USERID的值是乱码!!<br>&nbsp; &nbsp; &nbsp; &nbsp; //ShowMessage(temp); // 如果没有屏蔽这句,在DLL中跟踪会发现传递的userID的值是乱码.<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if Assigned(MgetuserName) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MgetuserName(UserID,vName);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ShowMessage(vName);<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; if cHnd&gt;0 then<br>&nbsp; &nbsp; &nbsp; freelibrary(cHnd);<br>&nbsp; &nbsp; FreeMem(vName);<br>&nbsp; end;<br>end;<br><br>
 
DEPHI 5 开发人员指南<br>http://lib.cqu.edu.cn/pcbook/FILES/PRO-DEPHI-EXPLOIN.htm<br>认真看一下这本书的第9章,不过要装上Acrobat Reader 5.1才看得到<br>
 
app2001:你提供的资料有一定的帮助,但我还是不明白我的问题<br><br>需要帮助!
 
我觉得,你的函数为那个变量在内存中申请了一个地址,所以你一定要用PCHAR来将数据传送到指针指向的那个地址,别外你有没有试过ShowMessage(string(temp));<br>这样的方式来查看一下数据?
 
Delphi 程序中的优化非常厉害,<br>如果一个局部字符串,在后面的代码中不再使用,那么他可能已经不存在了<br>所以你的指针也就没有意义了<br><br>按下面的写法,应该不会有什么问题:,而且也不用分配内存,不用担心内存泄漏了<br><br>假设你的函数这么声明:<br>Function GetUserName(userid:Pchar; vName:PChar):boolean;<br><br>调用如下:(是从你的程序翻译过来的)<br><br>var<br>&nbsp; GetuserName:TMgetuserName;<br>&nbsp; DllPathFile,temp, vName: String;<br>&nbsp; cHnd: THandle;<br>begin<br>&nbsp;cHnd:=0;<br>&nbsp;DllPathFile :='my.dll';<br>&nbsp;if NOT FileExists(DllPathFile) Then Exit;<br>&nbsp;Try<br>&nbsp; &nbsp; cHnd :=LoadLibrary(PChar(DllPathFile));<br>&nbsp; &nbsp; if cHnd&gt;0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp;MgetuserName:=GetProcAddress(cHnd,'MgetuserName');<br>&nbsp; &nbsp; &nbsp; &nbsp;temp:='291';<br>&nbsp; &nbsp; &nbsp; &nbsp;if Assigned(MgetuserName) then<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SetLength(vName, 200);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MgetuserName(PChar(UserID,vName), PChar(vName));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ShowMessage(vName);<br>&nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp;end;<br>&nbsp;finally<br>&nbsp; &nbsp;if cHnd&gt;0 then<br>&nbsp; &nbsp; &nbsp;freelibrary(cHnd);<br>&nbsp;end;<br>end;<br>
 
您的问题在于对PChar的理解[:)]:<br>1.PChar的本质是指针。<br>2.PChar指向的内存如果没有正确分配,或分配后但释放了,内容即为乱码。<br>3.如果您交给别的例程用指针的方式使用一段内存,请在这个例程使用结束前保护好这段内存。<br>-------------------------------------------------------------------------------<br>&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;UserID:=PChar(temp); // 只有这样赋值,参数才能正确传递,如果用 &nbsp; &nbsp;<br>&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // GetMem,setPCopy的方法,传递的<br>&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // USERID的值是乱码!!<br>赋值的目的是您应确知 UserID 指向的内存。<br>&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;//ShowMessage(temp); // 如果没有屏蔽这句,在DLL中跟踪会发现传递的userID的值是乱码.<br>Showmessage中是否有内存分配待考。但您的 Temp 此时可能已经被释放了(检查编译优化选项)。<br>您可以试试将这个语句放到调用过 Dll 函数之后。
 
app2001:<br>&nbsp; &nbsp;ShowMessage(string(temp)),增加类型转换应该是无效的,因为DELPHI对同类型转换是忽略的.<br>&nbsp; lich:<br>&nbsp; &nbsp; 非常多谢你帮我吧声明中的VAR去掉.<br>一曲新词酒一杯:<br>&nbsp; &nbsp; 如果您交给别的例程用指针的方式使用一段内存,请在这个例程使用结束前保护好这段内存 也很有帮助.<br>多谢各位的帮助.先加分了.<br><br>&nbsp; 不知有没有对于传递一列数据(因为TSTRINGLIST不太安全)的建议?<br><br>
 
怎么没有地方加分!!<br>
 
对于导出的函数应该使用 stdcall 声明
 
多人接受答案了。
 
后退
顶部