开发工具:DELPHI5、VC++6
操作系统:WIN98
限制:DLL用VC开发,DELPHI使用
问题:DELPHI可以加载并使用VC写的DLL函数了,但是无法传递参数数值,无论修改DELPHI的传入参数都显示的是一个固定数值,郁闷了……该如何去解决?由于只有一点小问题了,故只把最关键的部分写下来。以下是VC写的DLL函数入口部分
>----------------------------
extern "C" _declspec(dllexport)
void myfunc(int n)
{
char s[255];
MessageBox(NULL,itoa(n,s,10),"传入的值是",0);
}
----------------------------<以下是DELPHI的DLL使用部分
>----------------------------
界面:一个FORM,一个SPINEDIT,一个BUTTONprocedure myfunc(m:integer);far;External 'mydll.dll';//静态加载DLL{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);//一个
begin
 myfunc(spinEdit1.Value);//将Form1的一个
end;
----------------------------<

解决方案 »

  1.   

    后面的
    procedure TForm1.Button1Click(Sender: TObject);//一个
    begin
     myfunc(spinEdit1.Value);//将Form1的一个
    end;
    ----------------------------<应该是:
    procedure TForm1.Button1Click(Sender: TObject);//一个BUTTONCLICK事件
    begin
     myfunc(spinEdit1.Value);//将Form1的一个SPINEDIT数值传入DLL函数
    end;
    ----------------------------<然后弹出对话框里的数就不对了
      

  2.   

    调用DLL有两种方法,一种是在应用程序装载时调用,另一种是在应用程序运行时调用。(1) 装载时调用DLL在调用DLL的Pas文件中,对DLL函数进行外部声明,声明应位于Implementation后,形式如下:Implementation
      Function functionname(argment):Boolean;far;External 'DllName'; 其中External关键字后面的引号内是DLL的文件名,该文件一般应放在系统的system目录下,或与调用它的项目同一目录。声明以后即可在Pas文件任何地方引用DLL函数。装载时调用DLL的优点是速度较快,程序间也可共享代码。(2) 运行时调用DLLDLL的另一种调用方法是在运行时调用。这种方法要调用到Windows的API函数LoadLibrary,GetProcAddress,FreeLibrary等。此方法主要用于调用其它语言,特别是C++编译的DLL。假定你欲调用的DLL中包括一个函数:Function checkpwd(pwd:string):boolean;export; 那么,首先在欲调用DLL的程序Type类型声明处加入一句:Type
      Tcheckpwd= function(pwd:string):boolean; 此句的作用如同C++中声明的函数指针。然后定义如下变量∶Var
      aptr:TFarproc;
      lhnd:THandle;
      flag:boolean; 其中Aptr,lhnd两变量声明必须有,flag是DLL函数返回值,视情况而定。在调用DLL处加入如下语句进行DLL装载:lhnd:=Loadlibrary('路径:DLL文件名');{如lhnd:=Loadlibrary('c:\project1.dll');
      aptr:=GetprocAddress(lhnd,'checkpwd'); 下面可直接调用DLL了:flag:=Tcheckpwd(aptr)( 'pwd');{根据函数填相应的变量参数} 调用完以后,用FreeLibrary释放DLL占用的内存:FreeLibrary(lhnd); 
      

  3.   

    DLL调用是实现了,如果DLL里仅是个MessageBox显示一个字符串还好,如果显示用DELPHI程序传入的参数就有问题了。关键是DLL获得数值与DELPHI程序传入数值不对!应该如何修改DLL的编写部分或DELPHI的调用部分令传入的数值正确。例如:我在SpinEdit里输入数值1,则MessageBox里显示14495580,输入数值200,还是显示14495580,但是程序如上应该是这样写的啊,怎么传入的参数没有作用啊!难道VC只能调用VC写的DLL,DELPHI只能调用DELPHI写的DLL?郁闷中……
      

  4.   

    不知道是不是由于C和PASCAL函数调用机理不同,我将myfunc申明为void PASCAL myfunc(int n),可以编译为DLL后在DLL内部怎么变成_myfunc@4了啊(我用工具看的)?里面有@触犯PASCAL关键字叫我怎么用DELPHI去调用啊?
      

  5.   

    2.4 Delphi 调用32 位动态库方法
    语法:
    [Public Private | protected] Function FunctionName([Var] [Arg1:DataType1;]
    [Arg2:DataType2;...]) [:ReturnDataType]; far;stdcall;external ‘libname libname’ [Name
    AliasName];
    调用语句的语法包含下面部分:
    关键字Public 可选的。表示函数可以被程序代码中的任意部分访问。
    关键字Private 可选的。表示函数在声明类的单元(源代码)外不能访问。
    关键字Protected 可选的。部分地表示保护函数,保护元素只能被当前类和它的子类访问。
    关键字Function 必需的。表示调用函数,函数有返回值。
    FunctionName 必需的。调用外部函数的名称,区分大小写。
    关键字Var 可选的。表示通过引用传递参数。函数参数可以用值传递增,也可以通过引用传递。通过引用传传递参数,就意味着它的值没被复制到存放函数例程参数的堆栈中,避免复制就意味着程序执行速度加快了。通过引用传值,这将允许过程和函数改变参数的值。
    ArgN:DataTypeN 可选的。参数名以及参数类型,传递的参数类型可以是:Shorint,Smallint,Longint,Integer(16/32),Single,Double,Extended,Currency,Date,Pchar,Object,Variant 等。
    ReturnType 可选的。表示函数返回值的类型。
    Stdcall 必需的。表示传递约定,这样调用模块(应用程序),与被调用模块(DLL)就使用相同的参数约定。
    关键字external 必需的。声明访问外部函数。
    Libname 必需的。访问的DLL 名称,16 位Delphi 中外部声明不带扩展名的库名。
    Name ‘AliasName’ 可选的。Name 指令可以为外部函数起别名,避免与系统例程和函
    数名相冲突。
    外部程序调用的DLL 函数,必须遵照下列规则:
    a. 必须列在DLL 的exports 子句中。
    b. 在Delphi3 中,调用函数还需被声明为stdcall,来使用标准的WIN32 参数传递技
    术。代替优化的register 参数传递技术。
    c. 在WIN32 中,DLL 可以使用全局数据,该数据将不会通过调用应用程序来分享,每
    当应用程序装载DLL 时,它在自己的地址空间中存储着DLL 的全局数据。
      

  6.   

    例如:BOOL CommOpen(int integer, int nBaud)
    Function CommOpen(nPort:integer;nBaud:integer):boolean;Cdecl;
    far;External 'Commpro.DLL' name 'CommOpen';
      

  7.   

    好了,你这个问题我来解决!嘿嘿
    对于静态连接
    在定义的时候这样改
    procedure myfunc(m:integer);far;External 'mydll.dll';stdcall;
    “如果是win98以上的操作系统far就可以不用加了”你可以先试一下,不行的话
    再在vc输出的函数定义中再加一个"CALLBACK",如下extern "C" _declspec(dllexport)
    void CALLBACK myfunc(int n)
      

  8.   

    对于VC输出函数的名称有_@的问题可以这样解决
    在vc工程里添加一个源文件,把后缀改为def
    然后这样写
    export
          你的函数名
      

  9.   

    以下我贴出我自己的代码
    用VC写DLL,DELPHI调用,调试通过VC
    //a1.cpp
    #include "stdafx.h"
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {
        return TRUE;
    }
    int CALLBACK test(int a)//输出的函数
    {
    return a+1;
    }//a1.def
    EXPORTS
            testDELPHI下面是动态调用
    县声明一个类型
    type
      TA1 = function (i: integer):integer;stdcall;procedure TForm1.Button1Click(Sender: TObject);
    var
        h: cardinal;
        i: integer;
        a1: TA1;
    begin
        //i:=6;
        try
        h:=loadlibrary('a1.dll');
        @a1:=getprocaddress(h,'test');
        i:=a1(9);
        showmessage(inttostr(i));
        finally
        freelibrary(h);
        end;
    end;
      

  10.   

    Dephi中的Call Convention 应该用cdecl声明。
    procedure myfunc(m:integer);edecl;External 'mydll.dll';
      

  11.   

    >----------------------------
    extern "C" _declspec(dllexport)
    WINAPI void myfunc(int n)
    {
    char s[255];
    MessageBox(NULL,itoa(n,s,10),"传入的值是",0);
    }
    ----------------------------<
    就对了
      

  12.   

    楼上不对。
    C中缺省的调用方式是cdecl,WINAPI实际上就是FAR PASCAL,也就是stdcall。
    Delphi中缺省的调用方式为register,far声明没有意义。
    这是各种调用方式的参数传递顺序及清栈方法:
    Directive Parameter order Clean-up Passes parameters in registers?
    register Left-to-right Routine Yes
    pascal Left-to-right Routine No
    cdecl Right-to-left Caller No
    stdcall Right-to-left Routine No
    safecall Right-to-left Routine No
      

  13.   

    多谢各位大虾,采用zhou80bin(彬彬)的方法实现了,不过
    @a1:=getprocaddress(h,'myfunc');//我在VC中申明为myfunc
    需要写成
    @a1:=getprocaddress(h,'_myfunc@4');
    才能正常使用,为什么啊?VC中申明的myfunc怎么用个CALLBACK编译后在DLL中就变名字了啊?还有一事不明,在DELPHI中用动态加载太麻烦了。由于程序没必要中途释放加载的DLL,因此我想采用静态加载(程序启动时加载)的方式,这样写起来也简单些。可以老是有问题,要么参数没传入,要么程序没响应了。我在DELPHI想采用静态加载的方式如下:
    function *****;External 'mydll.dll';
    该如何修改程序呢?
      

  14.   

    你好好看看我给你的例子
    关于
    @a1:=getprocaddress(h,'myfunc');//我在VC中申明为myfunc
    需要写成
    @a1:=getprocaddress(h,'_myfunc@4');
    的问题,我已经在里面说了,好好看看!!!!!静态连结也是一样的
    这样就可以了function *****;External 'mydll.dll';stdcall;
      

  15.   

    弄好啦,谢谢啦,找散分按钮ing……