大家好,我在用Delphi调用C++动态库中的函数时碰到一个奇怪的问题,调了好久不知该如何解决,请大家帮忙看看!程序的部分代码如下:
(调用这个过程时出错)
procedure  TMainForm.GetParFromSystem; //自定义的一个public过程
var
  nRet:integer;
  aPar:PDxSystemPar;     //自定义的结构指针类型,和DLL中将要调用的函数的参数的类型相同
  Handle:THandle;
  psiGetSystemPar:TpsiGetSystemPar;  //定义函数类型变量,和被调用的DLL库中的C函数同名
  //aPar:Array of TDxSystemPar;      //结构类型,与DLL中同名类型一致
begin
  //SetLength(aPar,1);
  New(aPar);
  Handle := LoadLibrary('MyDll.DLL'); //MyDll.Dll是要调用的C++动态库
  if Handle <> 0 then
  begin
    @psiGetSystemPar := GetProcAddress(Handle,'psiGetSystemPar');
    //psiGetSystemPar是动态库中的要将调用的函数的名称
    if @psiGetSystemPar <> nil then
    begin
      nRet:=psiGetSystemPar(aPar);
      //通过该函数往结构指针aPar中赋值,我在单步调试发现赋值结果是正确,即值已赋到aPar中了
      if(nRet < 0) then
      begin
        MessageDlg('读取信息失败!',MtInformation,[mbok],0);
      end
      else
      begin
        //下一步取出已被赋值的的结构中的一个字符型的值给全局变量nStationNum
        nStationNum := ord(aPar^.StationNum);//调试时发现此赋值可以得到正确值
       //程序调到此步时,结果还是正确的,但接下来问题出现了
       //我在调试中发现如果光有上面这样一个赋值语句,函数在执行完所以语句跳出时会出错
       //错误代码如下:
       //Acess Violation at address 01121F7,write of address 18DA5F35
       //上述错误代码每次RUN都出现,但地址不一样,有时出现的错误提示是:
       //faulted with message" access violation at 0x004059c1,write ofaddress   
    // 0x00030d3c,同样每次地址都有些变化,但基本信息就是提示非法访问,错误代码$C0000005     //但是,奇怪的是,如果我随便在使用该结构中的任意几个值,比如下面语句
        YcListbox.Items.Add(IntToStr(aPar^.ShiftTime1));
        YcListbox.Items.Add(IntToStr(aPar^.ShiftTime2)); 
      //这时程序运行正常,Run没有问题!但如果去除,就出现上述问题!
      //也就是问题是在对结构的成员没有使用或者使用的没有达到一定数量时就报非法访问的错误 
      end;
    end
    else
      ShowMessage('调用函数GetProcAddress出错!');
    FreeLibrary(Handle);
  end;
  Dispose(aPar);
//
end;    //每次都是运行到最后跳出这个函数时就弹出Debugger错误提示框
但是不知道为什么随便再多使用几个结构成员它又运行正常,如果不用或用的不够就出问题!我不知道为什么会出现非法访问的提示,我把参数换成动态数组试过也不行!不知道是什么原因,请大家帮忙看看,谢谢!
C++库中被调用函数的原型为:
int psiGetSystemPar(struct DxSystemPar aPar[]);
这个函数是没有问题的,在C++中使用一切正常!调用C++库中的函数我只需取StationNum的值,但如果我仅仅取它的话,程序就出错!
提示"project c\:TestPrj.exe faulted with message:"access violation at 0x0012f6ff; write address 0x6000436c', process stoped ues step or run to continue!
但是如果我像程序中写的那样,把一些其余的成员如shifttime1,shifttime2等等加入到一个列表框的话,程序运行没有问题,并且至少要使用到该结构中的三个成员,用两个都报错!
PDxSystemPar是指向TDxSystemPar结构类型的指针,TDxSystemPar结构的定义如下:TDxSystemPar =  Record    StationNum:char;              ShiftNum:char;         
    PeakNum:char;            
    ValleyNum:char;         
    SmoothNum:char;            ShiftTime1:word;      
    ShiftTime2:word;
    ShiftTime3:word;    PeakTime1:LongWord;    
    PeakTime2:LongWord;     
    PeakTime3:LongWord;     
    ValleyTime1:LongWord;     
    ValleyTime2:LongWord;     
    ValleyTime3:LongWord;    
    SmoothTime1:LongWord;    
    SmoothTime2:LongWord;    
    SmoothTime3:LongWord;         YkTimeout:char;     
    PlanTime:char;               
    ExpressTime:char;               
    FreshTime:char;                   GpsOnOff:char;          
    SwitchOnOff:char;                   GpsPort:integer;         
    SwitchPort:integer;      
    GpsPort1:integer;        
    SwitchPort1:integer;  
    GpsAddr:Array[1..20]of char;
    SwitchAddr:Array[1..20]of char;   
    GpsAddr1:Array[1..20]of char; 
    SwitchAddr1:Array[1..20]of char;  

  end;
请大家提示一下可能出错的地方,谢谢!

解决方案 »

  1.   

    1。你在C++里用sizeof(TDxSystemPar)和Delphi里用sizeof(TDxSystemPar)看看两个结构体是否大小相同2。
    int psiGetSystemPar(struct DxSystemPar aPar[]);
    你C++代码要求从aPar获取的到底是一个指针还是一个数组呢?
      

  2.   

    有用Pchar吗?
    好像string在DLL里有问题。
      

  3.   

    试试在那个函数的DELPHI声明后面加上cdecl。
    int psiGetSystemPar(struct DxSystemPar aPar[]);
    你C++代码要求从aPar获取的到底是一个指针还是一个数组呢?
    我也有 Eastunfail一样的疑问。。如果发现两个SIZEOF不一样,试试。。
    TDxSystemPar =  Record

    TDxSystemPar =  packed Record
      

  4.   

    int psiGetSystemPar(struct DxSystemPar aPar[]);
    你C++代码要求从aPar获取的到底是一个指针还是一个数组呢?C++中 指针跟数组是差不多的 传入 数组首地址即可 @arr.
      

  5.   

    是啊。C/C++里数组就是指针。但他代码里是怎么处理这个aPar的呢?我考虑的问题是他在代码中把aPar当作数组处理还是当作指针处理
      

  6.   

    我用sizeof试过了,两个结构的大小是一样的,我测了两个,一个是152字节,一个是144字节,这个是必须要相等的,不然根本就从C++函数中取不回来值!
      

  7.   

    我在Delphi中的函数声明是用的Stdcall,用cedcl有什么不同吗?
      

  8.   

    可能是这样的... aPar:PDxSystemPar;     //自定义的结构指针类型,和DLL中将要调用的函数的参数的类型相同
    // dll知道这个 结构体么...
    C++ 中为struct delphi为 record
    虽然内存分布好像是一样的 可是不能被正确的识别...
      

  9.   

    stdcall 与cdecl 差别大了包括 参数入栈方式 谁负责分配堆栈 清理堆栈等
    WIN API函数都为stdcall cdecl一般是调用c/c++函数使用的方式