dll code 
--------
library SerReger;uses
  SysUtils,
  Classes,
  UCom in 'UCom.pas';var
  Info:THardwareInfo;{$R *.res}function Test1(a,b:integer):integer;
begin
  Result:=a+b;
end;function Test2(tx:string):string;
begin
  Result:=tx+'b';
end;function ResPWDStr(Key:string):string;
begin
   Result := key+'xxx';//
end;exports
  Test1,Test2;begin
end.--call code --function TfrmSysControl.testr(a,b:integer):integer;
var
  ReStr:function(a,b:integer):integer;
  DllHandle:hmodule;
  DllName:pchar;
begin
  DllName :=pchar(strPath+'SerReger.dll');
  DllHandle:=LoadLibrary(dllName);
  if DllHandle >0 then
    try
      //@ReStr:=GetProcAddress(DllHandle,'Test1');
      @ReStr:=GetProcAddress(DllHandle,'Test1');
      if @ReStr<>nil then
        Result := ReStr(a,b);
    finally
      FreeLibrary(DllHandle);
    end
  else
    ShowMessage('dll没有找到');
end;
function TfrmSysControl.test(Key:string):string;
var
  ReStrx:function(Key:string):string;
  DllHandle:hmodule;
  DllName:pchar;
begin
  DllName :=pchar(strPath+'SerReger.dll');
  DllHandle:=LoadLibrary(dllName);
  if DllHandle >0 then
    try
      @ReStrx:=GetProcAddress(DllHandle,'Test2');
      if @ReStrx<>nil then
        Result := ReStrx(Key);
    finally
      FreeLibrary(DllHandle);
    end
  else
    ShowMessage('dll没有找到');
end;
--问题--
为何在用test1 是不会报内存地址错误,而在调test2是却报内存地址错误。
  Showmessage(test('Text')); 
  showmessage(inttostr(testr(1,3)));

解决方案 »

  1.   

    新建个library之后,先别着急把自动生成的提示信息删了,里头都说的明明白白的了,人家不是白给你提示的
      

  2.   

    主程序、DLL同时加ShareMem,发布加上borlndmm.dll
      

  3.   

    转为PCHAR或函数声明加上stdcall试试
      

  4.   

    library文件中开头有一段注释, 根据注释可以解决.
    { 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. }library SerReger; uses
      ShareMem, //这个uses在你使用了这个.dll的所有项目的所有文件(包括.dpr)的uses第一句出现, 以及.dll工程所有文件中uses第一句出现 
      SysUtils, 
      Classes, 
      UCom in 'UCom.pas';function Test2(tx:string):string;stdcall;export; 
    begin 
      Result:=tx+'b'; 
    end;{$R *.res}exports
      Test2;begin
    end.//下面是调用, 注意在这个调用.dll函数的文件的uses第一句使用ShareMe, 及这个工程的.dpr文件开头uses第一句(保证正确退出)function TfrmSysControl.test(Key:string):string; 
    var 
      ReStrx:function(Key:string):string;stdcall; //stdcall非常重要
      DllHandle:hmodule; 
      DllName:pchar; 
    begin 
      DllName :=pchar(strPath+'SerReger.dll'); 
      DllHandle:=LoadLibrary(dllName); 
      if DllHandle >0 then 
        try 
          @ReStrx:=GetProcAddress(DllHandle,'Test2'); 
          if @ReStrx <>nil then 
            Result := ReStrx(Key); 
        finally 
          FreeLibrary(DllHandle); 
        end 
      else 
        ShowMessage('dll没有找到'); 
    end; 
      

  5.   

    写不写stdcall和字符串调用出错完全无关,只要主程序声明的DLL函数,和DLL实际导出的函数都写,或者都不写就行
      

  6.   

    “这个uses在你使用了这个.dll的所有项目的所有文件(包括.dpr)的uses第一句出现, 以及.dll工程所有文件中uses第一句出现”这句也是误导,只要工程文件第一个位置写了就行,根本不用所有文件都写。
      

  7.   

    经过测试验证,我按yejinson  的方可成功返回字符串,但在调用主程序关闭时,还是会报一个 invalid pointer opertion.应如何处理。我两边都有加ShareMem
      

  8.   

    .dpr的uses第一句出现ShareMem才可以关闭不报错. 8楼的说我误导别人? 我只是习惯这样写, 再说都告诉你去看那段注释了, 难道你不会英文?
      

  9.   

    不是,我是说后半句而已,前面dpr那里是正确的