dll 中方法如下type 
    TmyArray=array   of   array   of   PChar;function getAllDepartmentDoctors1(departmentId: PChar): TmyArray; stdcall;
var
  myarray1:TmyArray;
  Query: TADOQuery;
  count: Integer;
begin
  CoInitialize(nil);
  Query := TADOQuery.Create(nil);
  try
    try
      Query.Close;
      Query.ConnectionString := getConnectionString;
      Query.SQL.Clear;
      Query.SQL.Add('select userBasicInfo.FRK001_01 from TRK001 as userBasicInfo,'
        + ' TGY002 as doctor,TGY001 as department'
        + ' where userBasicInfo.FRK001_01= doctor.FRK001_01 and'
        + ' department.FGY001_01 = doctor.FGY001_01'
        + ' and department.FGY001_01=''320311000-01''');
      Query.Open;
      SetLength(myarray1, Query.RecordCount,Query.FieldCount);
      count := 0;
      Result := myarray1;
    except
      Query.Close;
      Query.Free;
      CoUninitialize;
      ShowMessage('²Ù×÷Êý¾Ý¿âÒì³£:' + Exception(ExceptObject).Message);
    end;
  finally
    Query.Close;
    Query.Free;
    CoUninitialize;
  end;end;
调用的方法如下
type
  TmyArray = array of array of PChar;function getAllDepartmentDoctors1(departmentId: PChar): TmyArray; stdcall;
  external 'dll.dll';procedure TForm1.Button4Click(Sender: TObject);
var
  HInst: THandle;
  FPointer: TFarProc;
begin
  try
    HInst := LoadLibrary('dll.dll');    if HInst > 0 then begin
      FPointer := GetProcAddress(HInst, 'getAllDepartmentDoctors1');
      if FPointer <> nil then
      begin
        getAllDepartmentDoctors1(PChar('test'));
      end
      else
        ShowMessage('error');
      FreeLibrary(HInst);
    end
    else ShowMessage('dll not found');
  except
    ShowMessage('错误:' + Exception(ExceptObject).Message);
  end;我点击按钮4 的时候去调用 
前几次不会出错,大约到 第六次的时候就会有内存错误
我都纳闷死了,为什么前几次没有错误 非得连续调用了好几次会出现错误呢

解决方案 »

  1.   

    你的这种写法其实不严谨,动态数组本身是在堆中动态分配的内存。
    正常情况下,你应该是在exe中分配内存,并将内存传递到dll中,然后使用。
    或者,你在DLL中分配内存,然后传给exe使用,然后在dll中释放内存。另外,你在 dll 中声明的 TmyArray 类型,和在exe 中声明的 TmyArray 类型,虽然形式上是一样的,但是他们是两种数据类型,呵呵,意外吧。你可以查看下他们的rtti信息。
    下面是一个简单的测试证明他们是两种数据类型DLL中type
      TmyArray = array of array of PChar;function abc(): Integer;
    begin
      Result := Integer(TypeInfo(TmyArray))
    end;exports
      abc;Exe中type
      TmyArray = array of array of PChar;function abc(): Integer; stdcall; external 'Project2.dll';procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowMessage(Format(
        '$%s (Exe中TmyArray的TypeInfo)'#13#10'$%s (dll中TmyArray的TypeInfo:)',
        [IntToHex(Integer(TypeInfo(TmyArray)), 8),
         IntToHex(Integer(abc()), 8)]));
    end;
      

  2.   

    如果一定要在dll中分配内存,可以考虑使用回调函数
    简单的例子如下exe中type
      TMyArray = array of array of Integer;
      PMyArray = ^TMyArray;
      TExeFun = function (Mem: Pointer): Integer;function abc(pFun: TExeFun): Integer; stdcall; external 'Project2.dll';function exefun(mem: Pointer): Integer;
    var
      s: String;
      i, j: Integer;
    begin
      s := '';
      for i := 0 to 4 do
        for j := 0 to 4 do
          s := s + IntToStr(PMyArray(mem)^[i][j]) + ',';
      ShowMessage(s);
      Result := 0;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      abc(exefun);
    end;dll 中type
      TMyArray = array of array of Integer;
      PMyArray = ^TMyArray;
      TExeFun = function (Mem: Pointer): Integer;function abc(pFun: TExeFun): Integer; stdcall;
    var
      MyArray1: TMyArray;
      i, j: Integer;
    begin
      SetLength(MyArray1, 5, 5);
      for I := 0 to 4 do
        for j := 0 to 4 do
          MyArray1[i][j] := (I + 1) * (j + 1);
      pFun(Pointer(@MyArray1));  Result := 0;
    end;exports
      abc;上面的方式就可以实现谁分配谁释放的原则,呵呵。
    另外,楼主声明的是PChar类型的数组,估计数组中还需要保存字符串指针,通过回调的方式,也不用考虑这些字符串指针的内存问题了。不过需要说明的是:不要再exe中释放传回数组以及数组中的字符串指针指向的字符串。建议使用bpl而不是dll来完成这些操作。在bpl中就可以避免数据类型不一致以及内存分配问题