DLL中内存操作的问题----想用String的地址来返回字符串 ( 积分: 100 )

  • 主题发起人 主题发起人 江远
  • 开始时间 开始时间

江远

Unregistered / Unconfirmed
GUEST, unregistred user!
[?][?]使用时会报内存操作错误!<br>请高手帮助看一看如何解决.<br><br>1.&nbsp;&nbsp;&nbsp;DLL的生成程序<br>library&nbsp;Project1;<br>uses<br>&nbsp;&nbsp;SysUtils,&nbsp;Classes;<br>{$R&nbsp;*.res}<br>procedure&nbsp;SetString(StrAddr:Integer);stdcall;<br>begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PString(StrAddr)^&nbsp;&nbsp;&nbsp;:=&nbsp;'123ABC';<br>end;<br>exports<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetString;<br>begin<br>end.<br><br>2.&nbsp;调用程序(部分)<br>.....<br>procedure&nbsp;SetString(Addr:integer);stdcall;external&nbsp;'Project1.dll';<br>type<br>&nbsp;&nbsp;TForm1&nbsp;=&nbsp;class(TForm)<br>&nbsp;&nbsp;&nbsp;&nbsp;Button1:&nbsp;TButton;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Button1Click(Sender:&nbsp;TObject);<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;public<br>&nbsp;&nbsp;end;<br>var<br>&nbsp;&nbsp;Form1:&nbsp;TForm1;<br>implementation<br>{$R&nbsp;*.dfm}<br>procedure&nbsp;TForm1.Button1Click(Sender:&nbsp;TObject);<br>var<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTmp&nbsp;:&nbsp;string;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iAddr&nbsp;:&nbsp;Integer;<br>begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iAddr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:=&nbsp;Integer(@sTmp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetString(iAddr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage(sTmp);<br>end;
 
哪壶不开拎哪壶!<br>Delphi的String为了兼容性考虑,本身就有很多问题。你这么搞不是自己给自己找事?
 
看生成DLL时上面那段字<br>目前来说有几种解决方案:<br>1.在.dpr的uses首位添加SimpleShareMem(Delphi2006自带的,如果是D7装个RTL)<br>2.采用接口呼叫和返回(推荐)。
 
SimpleShareMem是个什么东东,能介绍一下吗?
 
自己顶!<br>不过我必须这么来用,请问各个有什么办法?我采用的是D7
 
好象在DLL生成程序中这样写就没事,但是会多一个弹出框,各位DX指点一下下<br>procedure&nbsp;SetString(StrAddr:Integer);stdcall;<br>begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PString(StrAddr)^&nbsp;&nbsp;&nbsp;:=&nbsp;'123ABC';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage('asdf');&nbsp;&nbsp;//新加这一行就不会报错了<br>end;
 
最安全和最方便团队开发的方式是采用接口<br>SimpleShareMem来自于Fast&nbsp;MM,是个内存管理,经过实测,效率比不添加至少提高了30%。
 
你在做dll时,代码会自动产生这样的注释,不知你注意没有:<br>Important&nbsp;note&nbsp;about&nbsp;DLL&nbsp;memory&nbsp;management:&nbsp;ShareMem&nbsp;must&nbsp;be&nbsp;the<br>&nbsp;&nbsp;first&nbsp;unit&nbsp;in&nbsp;your&nbsp;library's&nbsp;USES&nbsp;clause&nbsp;AND&nbsp;your&nbsp;project's&nbsp;(select<br>&nbsp;&nbsp;Project-View&nbsp;Source)&nbsp;USES&nbsp;clause&nbsp;if&nbsp;your&nbsp;DLL&nbsp;exports&nbsp;any&nbsp;procedures&nbsp;or<br>&nbsp;&nbsp;functions&nbsp;that&nbsp;pass&nbsp;strings&nbsp;as&nbsp;parameters&nbsp;or&nbsp;function&nbsp;results.&nbsp;This<br>&nbsp;&nbsp;applies&nbsp;to&nbsp;all&nbsp;strings&nbsp;passed&nbsp;to&nbsp;and&nbsp;from&nbsp;your&nbsp;DLL--even&nbsp;those&nbsp;that<br>&nbsp;&nbsp;are&nbsp;nested&nbsp;in&nbsp;records&nbsp;and&nbsp;classes.&nbsp;ShareMem&nbsp;is&nbsp;the&nbsp;interface&nbsp;unit&nbsp;to<br>&nbsp;&nbsp;the&nbsp;BORLNDMM.DLL&nbsp;shared&nbsp;memory&nbsp;manager,&nbsp;which&nbsp;must&nbsp;be&nbsp;deployed&nbsp;along<br>&nbsp;&nbsp;with&nbsp;your&nbsp;DLL.&nbsp;To&nbsp;avoid&nbsp;using&nbsp;BORLNDMM.DLL,&nbsp;pass&nbsp;string&nbsp;information<br>&nbsp;&nbsp;using&nbsp;PChar&nbsp;or&nbsp;ShortString&nbsp;parameters.
 
英文注释已经很明显的告诉你该怎么做了,照做就行!
 
谢谢cnzzlp,我现在需要不是改变,是需要用内存直接来操作String,<br>我想知道为什么后面加上一个ShowMessage就可以了?<br>是不是可以使用别的方法也可以,但用户不需要显示另外的东东
 
delphi中的string在默认情况下长度可以达到2G,如果你坚持要使用string类型,就要引用ShareMem单元,而且必须是第一个引用的。既在uses语句后是第一个引用ShareMem的单元。如下如:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;uses&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;ShareMem,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;SysUtils,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Classes;<br>delphi&nbsp;2006自带了Fast&nbsp;MM的升级版SimpleShareMem,D7可以通过装个RTL来获得。<br>就加SimpleShareMem几个字而已,需要改变吗?不然就使用Pchar来传,或者改成接口形式。<br>无言。。。
 
最好谁分配谁释放,String类型涉及到计数等内存管理,EXE和DLL分别是两套内存管理器肯定会有问题,建议你的函数像API函数一样给个PChar和一个长度<br>procedure&nbsp;SetString(StrAddr:PChar;&nbsp;Len&nbsp;:&nbsp;Integer);stdcall;<br>var<br>&nbsp;&nbsp;S&nbsp;:&nbsp;string;<br>begin<br>&nbsp;&nbsp;S&nbsp;:=&nbsp;'123ABC';<br>&nbsp;&nbsp;copymemory(StrAddr,&nbsp;PChar(S),&nbsp;length(S));<br>end;<br>调用的时候<br>procedure&nbsp;TForm1.Button1Click(Sender:&nbsp;TObject);<br>var<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTmp&nbsp;:&nbsp;string;<br>begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setlength(sTmp,10);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetString(PChar(sTmp&nbsp;),10);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage(sTmp);<br>end;
 
算啦,我自己搞定了,只是中间用了一个Pchar中转了一下.谢谢各位!<br><br>不过我还是想知道为什么后面加上一个ShowMessage就不报错了???
 
为了兼容性考虑,DLL输出输入不要使用STRING。
 
用内存隐射文件啊!
 
后退
顶部