COM 操作:
编写C#dll的方法都一样,首先在vs2005中创建一个“类库”项目TestDll, using System.Runtime.InteropServices; namespace TestDll { public interface ITestClass { void YourProcedure(string param1); } [ClassInterface(ClassInterfaceType.None)] public class TestClass :ITestClass { public void YourProcedure (string param1) {
//自己的代码
} } } 完成之后,设置项目的属性--应用程序--程序集信息--“Make assembly COM-Visible”为选中状态。编译之后得到 TestClass.dll,把此dll放到Delphi主程序目录下(就是你现在所写的delphi项目下)。打开vs2005自带的工具“Visual Studio 2005命令提示”,输入 Regasm 路径/TestClass.dll 向系统注册此dll。 Delphi程序调用此Dll方式有两种: 一、打开vs2005自带的工具“Visual Studio 2005命令提示”,输入 TlbExp 路径/TestClass.dll 得到一个TestClass.tlb 文件。打开Delphi,选择“Project”--“import type library”找到刚才的TestClass.tlb,点击 CreateUnit,向delphi中引入一个com接口。 delphi 调用代码如下: var aClass: TestClass ; begin aClass : = CoTestClass.Create; aClass. YourProcedure ('参数'); end; 二、不需生成tlb文件,仿照调用Excel的方式。代码如下:
//注意:使用CreateOleObject时候,必须要uses Comobj 下,否则出错。 我自己加的 var aClass: Variant; begin aClass:= CreateOleObject('TestDll.TestClass'); aClass. YourProcedure ('参数');end;以上两种方法都可以调用成功,其中调用regasm.exe向系统注册dll是必需的。第一种方法需要生成tlb文件,并引入delphi中,操作繁琐,但可以看到接口的定义。第二种方法操作简单,但看不到接口的定义。
==============================================================
本人用第二种方法已正常实现功能,但DLL中一些自动创建的方法无法在外部直接调用,需要DLL准备特定的接口函数
另外的调用
调用DLL有两种方法,一种是在应用程序装载时调用,另一种是在应用程序运行时调用。 (1) 装载时调用DLL 在调用DLL的Pas文件中,对DLL函数进行外部声明,声明应位于Implementation后,形式如下: Implementation Function functionname(argment):Boolean;far;External 'DllName'; 其中External关键字后面的引号内是DLL的文件名,该文件一般应放在系统的system目录下,或与调用它的项目同一目录。声明以后即可在Pas文件任何地方引用DLL函数。 装载时调用DLL的优点是速度较快,程序间也可共享代码。 (2) 运行时调用DLL DLL的另一种调用方法是在运行时调用。这种方法要调用到Windows的API函数LoadLibrary,GetProcAddress,FreeLibrary等。此方法主要用于调用其它语言,特别是C++编译的DLL。 假定你欲调用的DLL中包括一个函数: Function checkpwd(pwd:string):boolean;export; 那么,首先在欲调用DLL的程序Type类型声明处加入一句:
注意:第一种是针对无返回值的,无返回值一般是procedure,而有返回值一般是function
1, typeTcheckpwd=function(pwd:string):boolean;stdcall; 2 Type Tcheckpwd= function(pwd:string):boolean; 此句的作用如同C++中声明的函数指针。 然后定义如下变量∶ Var aptr:TFarproc; lhnd:THandle; flag:boolean;
个人推荐这样定义:
Var aptr:TFarproc;VAR lhnd:THandle; 其中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); 异常处理:我用C#写的接口,封装成动态库,用DELPHI6调用时提示
1 2 3 4 5 6 7 8 9 10 11 | [Error] mscorlib_TLB.pas( 5194 ): Type 'Byte' is not yet completely defined [Error] mscorlib_TLB.pas( 5209 ): Type 'Double' is not yet completely defined [Error] mscorlib_TLB.pas( 5235 ): Type 'Int64' is not yet completely defined [Error] mscorlib_TLB.pas( 5267 ): Type 'Single' is not yet completely defined [Error] mscorlib_TLB.pas( 5747 ): Illegal type in OLE automation section: 'Byte' [Error] mscorlib_TLB.pas( 5754 ): Illegal type in OLE automation section: 'Single' [Error] mscorlib_TLB.pas( 5755 ): Illegal type in OLE automation section: 'Double' [Error] mscorlib_TLB.pas( 10874 ): Illegal type in OLE automation section: 'Byte' [Error] mscorlib_TLB.pas( 10881 ): Illegal type in OLE automation section: 'Single' [Error] mscorlib_TLB.pas( 10882 ): Illegal type in OLE automation section: 'Double' [Fatal Error] TestCOM_TLB.pas( 60 ): Could not compile used unit 'mscorlib_TLB.pas' |
网上找到了解决办法如下:
打开DELPHI6安装文件夹\Bin\tlibimp.sym文件,在文件尾部添加以下代码,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ;;==============================================;; ;; Map mscorlib CoClasses to better names ;; ;;==============================================;; [{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}:TypeNames] Byte=CLRByte Double=CLRDouble Single=CLRSingle Int16=CLRInt16 Int32=CLRInt32 Int64=CLRInt64 String =CLRString Object =CLRObject Array =CLRArray Enum=CLREnum Boolean =CLRBoolean Char=CLRChar Guid=CLRGuid Type=CLRType Void=CLRVoid Pointer=CLRPointer Exception=CLRException |
保存,然后重要的一步,Import Type Library 引入动态库,重新Create unit接口定义文件。