由于工程需要现在要调用动态连接库,名称为pmac.dll
里面有几个函数如:
int Com_Open ( int iPort, int iBaudrate );
void Com_Close ( int iPort );
int Com_IsOpen ( int iPort );
int Pml_9900e2_ReadReal ( int iPort, int iAddress, int * pValue );请问在Delphi中如何调用阿!

解决方案 »

  1.   

    <一>在Delphi中静态调用DLL top 调用一个DLL比写一个DLL要容易一些。首先给大家介绍的是静态调用方法,稍后将介绍动态调用方法,并就两种方法做一个比较。同样的,我们先举一个静态调用的例子。 unit Unit1; interface uses 
    Windows, Messages, SysUtils, Classes, Graphics, 
    Controls, Forms, Dialogs, StdCtrls; type 
    TForm1 = class(TForm) 
    Edit1: TEdit; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; var 
    Form1: TForm1; implementation {$R *.DFM} //本行以下代码为我们真正动手写的代码 function TestDll(i:integer):integer;stdcall; 
    external ’Delphi.dll’; procedure TForm1.Button1Click(Sender: TObject); 
    begin 
    Edit1.Text:=IntToStr(TestDll(1)); 
    end; end. 上面的例子中我们在窗体上放置了一个编辑框(Edit)和一个按钮(Button),并且书写了很少的代码来测试我们刚刚编写的Delphi.dll。大家可以看到我们唯一做的工作是将TestDll函数的说明部分放在了implementation中,并且用external语句指定了Delphi.dll的位置。(本例中调用程序和Delphi.dll在同一个目录中。)让人兴奋的是,我们自己编写的TestDll函数很快被Delphi认出来了。您可做这样一个实验:输入“TestDll(”,很快Delphi就会用fly-by提示条提示您应该输入的参数是什么,就像我们使用Delphi中定义的其他函数一样简单。注意事项有以 
    下一些: 一、调用参数用stdcall。 
    和前面提到的一样,当引用DLL中的函数和过程时也要使用stdcall参数,原因和前面提到的一样。 二、用external语句指定被调用的DLL文件的路径和名称。 
    正如大家看到的,我们在external语句中指定了所要调用的DLL文件的名称。没有写路径是因为该DLL文件和调用它的主程序在同一目录下。如果该DLL文件在C:\,则我们可将上面的引用语句写为external ’C:\Delphi.dll’。注意文件的后缀.dll必须写上。 三、不能从DLL中调用全局变量。 
    如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。 四、被调用的DLL必须存在。 
    这一点很重要,使用静态调用方法时要求所调用的DLL文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.dll文件”等运行错误。 <二>在Delphi中动态调用DLL top 动态调用DLL相对复杂很多,但非常灵活。为了全面的说明该问题,这次我们举一个调用由C++编写的DLL的例子。首先在C++中编译下面的DLL源程序。 #include extern ”C” _declspec(dllexport) 
    int WINAPI TestC(int i) 

    return i; 
    } 编译后生成一个DLL文件,在这里我们称该文件为Cpp.dll,该DLL中只有一个返回整数类型的函数TestC。为了方便说明,我们仍然引用上面的调用程序,只是将原来的Button1Click过程中的语句用下面的代码替换掉了。 procedure TForm1.Button1Click(Sender: TObject); 
    type 
    TIntFunc=function(i:integer):integer;stdcall; 
    var 
    Th:Thandle; 
    Tf:TIntFunc; 
    Tp:TFarProc; 
    begin 
    Th:=LoadLibrary(’Cpp.dll’); {装载DLL} 
    if Th>0 then 
    try 
    Tp:=GetProcAddress(Th,PChar(’TestC’)); 
    if Tp<>nil 
    then begin 
    Tf:=TIntFunc(Tp); 
    Edit1.Text:=IntToStr(Tf(1)); {调用TestC函数} 
    end 
    else 
    ShowMessage(’TestC函数没有找到’); 
    finally 
    FreeLibrary(Th); {释放DLL} 
    end 
    else 
    ShowMessage(’Cpp.dll没有找到’); 
    end; 大家已经看到了,这种动态调用技术很复杂,但只要修改参数,如修改LoadLibrary(’Cpp.dll’)中的DLL名称为’Delphi.dll’就可动态更改所调用的DLL。 一、定义所要调用的函数或过程的类型。 
    在上面的代码中我们定义了一个TIntFunc类型,这是对应我们将要调用的函数TestC的。在其他调用情况下也要做同样的定义工作。并且也要加上stdcall调用参数。 二、释放所调用的DLL。 
    我们用LoadLibrary动态的调用了一个DLL,但要记住必须在使用完后手动地用FreeLibrary将该DLL释放掉,否则该DLL将一直占用内存直到您退出Windows或关机为止。 现在我们来评价一下两种调用DLL的方法的优缺点。静态方法实现简单,易于掌握并且一般来说稍微快一点,也更加安全可靠一些;但是静态方法不能灵活地在运行时装卸所需的DLL,而是在主程序开始运行时就装载指定的DLL直到程序结束时才释放该DLL,另外只有基于编译器和链接器的系统(如Delphi)才可以使用该方法。动态方法较好地解决了静态方法中存在的不足,可以方便地访问DLL中的函数和过程,甚至一些老版本DLL中新添加的函数或过程;但动态方法难以完全掌握,使用时因为不同的函数或过程要定义很多很复杂的类型和调用方法。对于初学者,笔者建议您使用静态方法,待熟练后再使用动态调用方法。 
      

  2.   

    我按照上面的写如:
    unit MainFrm;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TMainForm = class(TForm)
        Com_Open: TButton;
        Com_State: TButton;
        Com_Close: TButton;
        procedure Com_StateClick(Sender: TObject);
        procedure Com_OpenClick(Sender: TObject);
        procedure Com_CloseClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      MainForm: TMainForm;implementationuses ImportDll;
    {$R *.dfm}
    Function Com_IsOpen(iPort:integer):integer;stdcall external 'pmac.dll' name 'Com_IsOpen';
    Function Com_Open(iPort,iBaudrate:integer):integer;stdcall external 'pmac.dll' name 'Com_Open';
    Function Com_Close(iPort:integer):integer;stdcall external 'pmac.dll' name 'Com_Close';
    procedure TMainForm.Com_StateClick(Sender: TObject);
    begin
      if Com_IsOpen(2)=0 then
        ShowMessage('串口2已经打开!')
      else
        ShowMessage('串口2没有打开!');
    end;procedure TMainForm.Com_OpenClick(Sender: TObject);
    begin
    //  Com_Open(2,9600);
    end;procedure TMainForm.Com_CloseClick(Sender: TObject);
    begin
     Com_Close(2);
    end;end.
    就会出现下面的错误,请问为什么啊?
    Missing operator or semicolon
      

  3.   

    void型
    在Delphi中调用时要用procedure相对应
      

  4.   

    谢谢Cipherliu
    我该过来了,还是不行啊!
    提示还是
    Missing operator or semicolon请教!!!!
      

  5.   

    应该是:
    Function Com_IsOpen(iPort:integer):integer;stdcall; external 'pmac.dll' name 'Com_IsOpen';
    Function Com_Open(iPort,iBaudrate:integer):integer;stdcall; external 'pmac.dll' name 'Com_Open';
    Function Com_Close(iPort:integer):integer;stdcall; external 'pmac.dll' name 'Com_Close';注意stdcall后面有";"
      

  6.   

    谢谢指教!
    上面三个函数已经搞好了.
    还有一个问题是,下面的函数应该怎样写阿?
    int Pml_9900e2_ReadReal ( int iPort, int iAddress, int * pValue );
    改为用Delphi形式
      

  7.   

    function Pml_9900e2_ReadReal (iPort:Integer; iAddress:Integer; pValue:PInteger):Integer; stdcall; external 'pmac.dll';
      

  8.   

    非常感谢!各位大哥的帮忙.小弟还有一个问题!在下面的函数中
    int Pml_9900e2_ReadReal ( int iPort, int iAddress, int * pValue );
    第三个参数int * pValue是用于把返回值放置在一个整型数组里面的,而pValue是指向该数组的指针,但是我怎样调用的.
    假设我已经定义了一个数组readData:array[0..35] of Integer;
      

  9.   

    我是这样做的,好像不行啊!不能调用Pml_9900e2_ReadReal 
    unit MainFrm;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      PInteger=^integer;  TMainForm = class(TForm)
        Com_Open: TButton;
        Com_State: TButton;
        Com_Close: TButton;
        ShowData: TListBox;
        Read_Data: TButton;
        procedure Com_StateClick(Sender: TObject);
        procedure Com_OpenClick(Sender: TObject);
        procedure Com_CloseClick(Sender: TObject);
        procedure Read_DataClick(Sender: TObject);
      private
        { Private declarations }
        readData:array[0..35] of integer;
      public
        { Public declarations }  end;var
      MainForm: TMainForm;implementationuses ImportDll;
    {$R *.dfm}
    //判断串口是否已经打开
    Function TCom_IsOpen(iPort:integer):integer;stdcall external 'pmac.dll' name 'Com_IsOpen';
    //打开串口
    Function TCom_Open(iPort,iBaudrate:integer):integer;stdcall external 'pmac.dll' name 'Com_Open';
    //关闭串口
    procedure TCom_Close(iPort:integer);stdcall external 'pmac.dll' name 'Com_Close';
    //读仪表中的数据
    //函数原型: int Pml_9900e2_ReadReal ( int iPort, int iAddress, int * pValue );
    Function TReadReal(iPort,iAddress:integer;pValue:PInteger):integer;stdcall external 'pmac.dll' name 'Pml_9900e2_ReadReal';
    procedure TMainForm.Com_StateClick(Sender: TObject);
    begin
      if TCom_IsOpen(2)=0 then
        ShowMessage('串口2已经打开!')
      else
        ShowMessage('串口2没有打开!');
    end;procedure TMainForm.Com_OpenClick(Sender: TObject);
    begin
      if TCom_Open(2,9600)=0 then
        ShowMessage('串口2打开失败!');
    end;procedure TMainForm.Com_CloseClick(Sender: TObject);
    begin
      TCom_Close(2);
      ShowMessage('串口2关闭成功!');
    end;procedure TMainForm.Read_DataClick(Sender: TObject);
    var
      i:integer;
    begin
      if TReadReal(2,2,@readData)=1 then
      begin
      for i:=0 to 35 do
        ShowData.Items.Add(IntToStr(readData[i]));
      end
      else
        ShowMessage('数据读取失败!');
    end;end.
      

  10.   

    可以这样声明:
    type
      ValueArray = array [0..35] of integer;
    ...function Pml_9900e2_ReadReal (iPort:Integer; iAddress:Integer; var pValue:ValueArray):Integer; stdcall; external 'pmac.dll';
      

  11.   

    其实看你的程序中使用的dll只做串口通信方面的事,还是用delphi写更方便。
      

  12.   

    我按照你的指点作了一下,好像还是不行啊!
    代码如下:
    unit MainFrm;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      ValueArray = array [0..35] of integer;  TMainForm = class(TForm)
        Com_Open: TButton;
        Com_State: TButton;
        Com_Close: TButton;
        ShowData: TListBox;
        Read_Data: TButton;
        procedure Com_StateClick(Sender: TObject);
        procedure Com_OpenClick(Sender: TObject);
        procedure Com_CloseClick(Sender: TObject);
        procedure Read_DataClick(Sender: TObject);
      private
        { Private declarations }
        readData:ValueArray;
      public
        { Public declarations }  end;var
      MainForm: TMainForm;implementationuses ImportDll;
    {$R *.dfm}
    //判断串口是否已经打开
    Function TCom_IsOpen(iPort:integer):integer;stdcall external 'pmac.dll' name 'Com_IsOpen';
    //打开串口
    Function TCom_Open(iPort,iBaudrate:integer):integer;stdcall external 'pmac.dll' name 'Com_Open';
    //关闭串口
    procedure TCom_Close(iPort:integer);stdcall external 'pmac.dll' name 'Com_Close';
    //读仪表中的数据
    //函数原型: int Pml_9900e2_ReadReal ( int iPort, int iAddress, int * pValue );
    Function TReadReal(iPort,iAddress:integer;var pValue:ValueArray):integer;stdcall external 'pmac.dll' name 'Pml_9900e2_ReadReal';
    procedure TMainForm.Com_StateClick(Sender: TObject);
    begin
      if TCom_IsOpen(2)=0 then
        ShowMessage('串口2已经打开!')
      else
        ShowMessage('串口2没有打开!');
    end;procedure TMainForm.Com_OpenClick(Sender: TObject);
    begin
      if TCom_Open(2,9600)=0 then
        ShowMessage('串口2打开失败!');
    end;procedure TMainForm.Com_CloseClick(Sender: TObject);
    begin
      TCom_Close(2);
      ShowMessage('串口2关闭成功!');
    end;procedure TMainForm.Read_DataClick(Sender: TObject);
    var
      i:integer;
    begin
      if TReadReal(2,2,readData)=1 then
      begin
      for i:=0 to 35 do
        ShowData.Items.Add(IntToStr(readData[i]));
      end
      else
        ShowMessage('数据读取失败!');
    end;end.
      

  13.   

    方法1:
    vc:
    void WINAPI DoSth(int* iValue)
    {
    for (int i=0; i<30; i++) {
    iValue[i] = i;
    }
    return;
    }delphi:
    procedure DoSth(iValue:pInteger);stdcall;external 'dlltest.dll';procedure TForm1.Button3Click(Sender: TObject);
    var
      iValue:array[0..29] of integer;
      i:Integer;
    begin
      DoSth(pinteger(@iValue));
      for I:=0 to 30-1 do begin
        Memo1.Lines.Add(inttostr(ivalue[i]));
      end;
    end;
      

  14.   

    方法2:
    vc:
    不变delphi:
    type
      ValueArray = array [0..29] of integer;procedure DoSth(iValue:ValueArray);stdcall;external 'dlltest.dll';procedure TForm1.Button3Click(Sender: TObject);
    var
      iValue:ValueArray;
      i:Integer;
    begin
      DoSth(iValue);
      for I:=0 to 30-1 do begin
        Memo1.Lines.Add(inttostr(ivalue[i]));
      end;
    end;