有人能教我如何调用c语言编写的动态数据连接库中的输入输出函数?(40分)

  • 主题发起人 主题发起人 archonwang
  • 开始时间 开始时间
A

archonwang

Unregistered / Unconfirmed
GUEST, unregistred user!
假设在一个用C语言写成的动态连接库sample.dll中存在这样一个输出函数:
int function sample(long * buffer);
输入函数:
float function sample2(long * buffer);
在delphi的unit中有如何声明和调用,谢谢
 
Delphi调用16位或32位动态库的方法

16位与32位动态库调用方法相同。
语法:

[Public Private | protected] Function FunctionName([Var] [Arg1:DataType1;] [Arg2:DataType2;...]) [:ReturnDataType]; far;stdcall;external 憀ibname?[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 慉liasName挘?裳。?琋ame指令可以为外部函数起别名,避免与系统例程和函数名称冲突。

外部程序调用的DLL函数,必须遵照下列规则:

(1)必须列在DLL的exports子句中。
(2)在Delphi3中,调用函数还需被声明为stdcall,来使用标准的WIN32参数传递技术。代替优化的register参数传递技术。
(3)在WIN32中,DLL可以使用全局数据,该数据将不会通过调用应用程序来分享,每当应用程序装载DLL时,它在自己的地址空间中存储着DLL的全部数据。
 
那上面这句具体该怎么写?
 
我在帮助中看到D7
When importing a C function that takes a variable number of parameters, use the varargs directive. For example,

function printf(Format: PChar): Integer; cdecl; varargs;

The varargs directive works only with external routines and only with the cdecl calling convention.

现在都糊涂了,不知道哪个是对的。所以,请大家帮忙 ~~~
 
先在声明罗在保留字implementation上面

function function sample(buffer:longint);integer; stdcall
external 'sample.dll' name 'sample';
function function sample2(buffer:longint);float; stdcall
external 'sample.dll' name 'sample2';
然后就象一般函数那样调用了,具体的你再找些资料来看看,这东西也是要多试的,我再给一些资料你看一下吧
10.2.2 调用DLLs

  有两种方法可用于调用一个储存在DLLs中的过程。
  1.静态调用或显示装载
  使用一个外部声明子句,使DLLs在应用程序开始执行前即被装入。例如:

  function Instr(SourceStr : PChar;Check : Char); Integer; far; external 'UseStr';

  使用这种方法,程序无法在运行时间里决定DLLs的调用。假如一个特定的DLLs在运行时无法使用,则应用程序将无法执行。
  2.动态调用或隐式装载
  使用Windows API函数LoadLibray和GetProcAddress可以实现在运行时间里动态装载DLLs并调用其中的过程。
  若程序只在其中的一部分调用DLLs的过程,或者程序使用哪个DLLs, 调用其中的哪个过程需要根据程序运行的实际状态来判断,那么使用动态调用就是一个很好的选择。

  使用动态调用,即使装载一个DLLs失败了,程序仍能继续运行。

10.2.3 静态调用

  在静态调用一个DLLs中的过程或函数时,external指示增加到过程或函数的声明语句中。被调用的过程或函数必须采用远调用模式。这可以使用far过程指示或一个{$F +}编译指示。
  Delphi全部支持传统Windows动态链接库编程中的三种调用方式,它们是:
  ● 通过过程/函数名
  ● 通过过程/函数的别名
  ● 通过过程/函数的顺序号

  通过过程或函数的别名调用,给用户编程提供了灵活性,而通过顺序号(Index)调用可以提高相应DLL的装载速度。

10.2.4 动态调用

10.2.4.1 动态调用中的API函数

  动态调用中使用的Windows API函数主要有三个,即:Loadlibrary,GetProcAddress和Freelibrary。
   1.Loadlibrary: 把指定库模块装入内存
  语法为:

  function Loadlibrary(LibFileName: PChar): THandle;

LibFileName指定了要装载DLLs的文件名,如果LibFileName没有包含一个路径,则Windows按下述顺序进行查找:

  (1)当前目录;
  (2)Windows目录(包含win.com的目录)。函数GetWindowDirectory返回这一目录的路径;
  (3)Windows系统目录(包含系统文件如gdi.exe的目录)。函数GetSystemDirectory返回这一目录的路径;
  (4)包含当前任务可执行文件的目录。利用函数GetModuleFileName可以返回这一目录的路径;
  (5)列在PATH环境变量中的目录;
  (6)网络的映象目录列表。

  如果函数执行成功,则返回装载库模块的实例句柄。否则,返回一个小于HINSTANCE_ERROR的错误代码。错误代码的意义如下表:

   表10.2 Loadlibrary返回错误代码的意义
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
错误代码         意        义
——————————————————————————————————————
    0 系统内存不够,可执行文件被破坏或调用非法
    2 文件没有被发现

    3 路径没有被发现
    5 企图动态链接一个任务或者有一个共享或网络保护错
    6 库需要为每个任务建立分离的数据段
     8 没有足够的内存启动应用程序
   10 Windows版本不正确
    11 可执行文件非法。或者不是Windows应用程序,或者在.EXE映
      像中有错误
    12 应用程序为一个不同的操作系统设计(如OS/2程序)

13 应用程序为MS DOS4.0设计
    14 可执行文件的类型不知道
    15 试图装载一个实模式应用程序(为早期Windows版本设计)
16 试图装载包含可写的多个数据段的可执行文件的第二个实例
    19 试图装载一个压缩的可执行文件。文件必须被解压后才能被装裁
    20 动态链接库文件非法
    21 应用程序需要32位扩展
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  假如在应用程序用Loadlibrary调用某一模块前,其它应用程序已把该模块装入内存,则Loadlibrary并不会装载该模块的另一实例,而是使该模块的“引用计数”加1。

  2.GetProcAddress:捡取给定模块中函数的地址
  语法为:

  function GetProcAddress(Module: THandle; ProcName: PChar): TFarProc;

Module包含被调用的函数库模块的句柄,这个值由Loadlibrary返回。如果把Module设置为nil,则表示要引用当前模块。

  ProcName是指向含有函数名的以nil结尾的字符串的指针,或者也可以是函数的次序值。如果ProcName参数是次序值,则如果该次序值的函数在模块中并不存在时,GetProcAddress仍返回一个非nil的值。这将引起混乱。因此大部分情况下用函数名是一种更好的选择。如果用函数名,则函数名的拼写必须与动态链接库文件EXPORTS节中的对应拼写相一致。
  如果GetProcAddress执行成功,则返回模块中函数入口处的地址,否则返回nil。

3.Freelibrary:从内存中移出库模块

  语法为:

  procedure Freelibrary(Module : THandle);

Module为库模块的句柄。这个值由Loadlibrary返回。
  由于库模块在内存中只装载一次,因而调用Freelibrary首先使库模块的引用计数减一。如果引用计数减为0,则卸出该模块。
  每调用一次Loadlibrary就应调用一次FreeLibray,以保证不会有多余的库模块在应用程序结束后仍留在内存中。

 
接受答案了.
 
后退
顶部