C#调用Delphi接口方法,有两种解决办法:

  一、将Delphi程序编译成一个COM组件,然后在C#里引用COM组件。

  二、非托管调用Dephi的DLL文件。

这里我们主要讲解一下第二种方法,讲第二种方法之前首先讲解下DllImport。

DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息。

DllImport属性应用于方法,要求最少要提供包含入口点的dll的名称。
     DllImport的定义如下:

代码

 1      [AttributeUsage(AttributeTargets.Method)]
 2      public class DllImportAttribute: System.Attribute
 3      {
 4       public DllImportAttribute(string dllName) {…} //定位参数为dllName
 5       public CallingConvention CallingConvention; //入口点调用约定
 6       public CharSet CharSet;                                   //入口点采用的字符接
 7       public string EntryPoint;                                  //入口点名称
 8       public bool ExactSpelling;                               //是否必须与指示的入口点拼写完全一致,默认false
 9       public bool PreserveSig;                                  //方法的签名是被保留还是被转换
10       public bool SetLastError;                                  //FindLastError方法的返回值保存在这里
11       public string Value { get {…} }
12      } 
13 

  上面DLL的名字有时需要写上路径的如[DllImport(@"C:\OJ\Bin\Judge.dll")]这样指定DLL的绝对路径就可以正常装载。

假如没有路径的话,DllImport会按照顺序自动去寻找的地方: 
     1、exe所在目录 
     2、System32目录 
     3、环境变量目录
     所以只需要你把引用的DLL 拷贝到这三个目录下, 就可以不用写路径了。

说明:    
    1、DllImport只能放置在方法声明上。   
    2、DllImport具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。   
    3、DllImport具有五个命名参数:    
        a、CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。    
        b、CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。   
        c、EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。    
        d、ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定 ExactSpelling,则使用默认值 false。    
      e、PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有 HRESULT返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使用默认值 true。    
      f、SetLastError 参数指示方法是否保留 Win32"上一错误"。如果未指定 SetLastError,则使用默认值 false。    
   4、它是一次性属性类。    
   5、此外,用 DllImport 属性修饰的方法必须具有 extern 修饰符。

下面讲解下如何调用:

用DllImport来调用的  一般是用非托管的。
  具体形式如下:1.[DllImport("WZFSE.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]。

  其中第一个参数是指要引用DLL的名字, 这个名字应该是个常量(否则会出错)。

要想在自己C#页面中引用,那就得在页面中申明这个函数。

  下面紧接着他的申明函数:
  2.public static extern void InitDll(IntPtr handle, bool methodAddress);(Dephi里怎么定义的函数在C#这里就要怎么定义:即Dephi的申明函数转换成C#的声明函数)。
  --申明一个函数就要引用下他的DLL 如1和2是紧密连在一起的。即再写一个函数就相应的应用起对应的DLL。

  下面是参数的引用:即Delphi的类型向C#的转换。

第一个参数类型:IntPtr这个类型可以申明为其他语言的句柄,指针等。
     若要实现其他语言类似C++的函数指针形式, 这时我们考虑用C#的委托来实现。

  

  下面说一下:如何将Dephi的窗体显示在自己的页面中(且不能显示Delphi窗体的标题栏,实现无缝的结合)。

  将dephi的窗体签入到自己的C#系统里 还有一点比较重要,我们是调用Delphi的窗体,此时显示在我们C#窗体中会有Delphi的窗体,

这时我们怎么办呢,  怎么去除Delphi中的窗体呢?  这时我们就需要用API函数了。 因为WINDOWS API是一种比较底层的语言,可以通过它进行操作。

在C#中是这么引用的: [DllImport("user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
                 public static extern void MoveWindow(IntPtr handler, int x, int y, int width, int height, bool repaint);

  下面插入一个类,这里面包含了怎么引用dephi的dll 以及怎么申明:

代码

 1  public class CompliancePlatDLL
 2     {
 3         public static string strPath = "";
 4         /// <summary>
 5         /// 初始化
 6         /// </summary>
 7         /// <param name="handle"></param>
 8         /// <param name="methodAddress"></param>
 9         [DllImport("WZFSE.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
10         public static extern void InitDll(IntPtr handle, bool methodAddress);
11         /// <summary>
12         /// 加载相应的服务
13         /// </summary>
14         /// <param name="str"></param>
15         /// <param name="str2"></param>
16         /// <param name="i"></param>
17         /// <returns></returns>
18         [DllImport("WZFSE.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
19         public static extern IntPtr wzLoadModule(string str, string str2, int i);
20         /// <summary>
21         /// 去除相应的服务
22         /// </summary>
23         /// <param name="handle"></param>
24         /// <returns></returns>
25         [DllImport("WZFSE.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
26         public static extern bool wzUnloadModule(IntPtr handle);
27 
28         #region API函数
29         /// <summary>
30         /// API函数 设置主辅窗体
31         /// </summary>
32         /// <param name="child"></param>
33         /// <param name="parent"></param>
34         [DllImport("user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
35         public static extern void SetParent(IntPtr child, IntPtr parent);
36         /// <summary>
37         /// API函数 移动窗体
38         /// </summary>
39         /// <param name="handler"></param>
40         /// <param name="x"></param>
41         /// <param name="y"></param>
42         /// <param name="width"></param>
43         /// <param name="height"></param>
44         /// <param name="repaint"></param>
45         [DllImport("user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
46         public static extern void MoveWindow(IntPtr handler, int x, int y, int width, int height, bool repaint);
47 
48         [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
49         public static extern long GetWindowLong(IntPtr hwnd, int nIndex);
50         /// <summary>
51         /// API函数 去除窗体的标题栏
52         /// </summary>
53         /// <param name="hwnd"></param>
54         /// <param name="nIndex"></param>
55         /// <param name="dwNewLong"></param>
56         /// <returns></returns>
57         [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
58         public static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
59         public const int GWL_EXSTYLE = -16;
60         public const int WS_EX_TRANSPARENT = 0x20;
61         public const int WS_EX_LAYERED = 0x80000;
62         public const int LWA_ALPHA = 2;
63         public const int WS_CAPTION = 0xC00000;
64         #endregion
65     }

其中API中的SetWindowLong这个方法是可以实现去除窗体的标题栏的,  具体调用SetWindowLong(common.p, GWL_EXSTYLE, GetWindowLong(handle, GWL_EXSTYLE) & (~WS_CAPTION));

  但一般完整利用API函数的调用是这样的

代码

 1          decallback de1 = new decallback(iscallback);//利用委托
 2                InitDll(this.Handle, de1(this.Handle));//初始化
 3                IntPtr p = wzLoadModule("DoRiskSetup", "", 0);//取得句柄
 4                if (p != (IntPtr)0)//判断该句柄不是弹出窗体时
 5                {
 6                    //去除dephi窗体的标题栏
 7                    SetParent(p, panel1.Handle);
 8                    SetWindowLong(p, GWL_EXSTYLE, GetWindowLong(p, GWL_EXSTYLE) & (~WS_CAPTION));
 9                    MoveWindow(p, 0, 0, panel1.ClientSize.Width, panel1.ClientSize.Height, false);
10                }

   SetWindowLong(IntPtr handle, int t,long l) 第一个参数为句柄,是你调的dephi窗体的句柄,第二个参数为整型,在dephi用常量GWL_EXSTYLE表示,表示要显示的样式,在C#中翻译过来的他值为(-16),而第三个函则为长整型和第二个参数一起表示要去除第一个参数句柄窗体的标题栏在Delphi中表示为:GetWindowLong(handle,GWL_EXSTYLE) and (not WS_CAPTION) 在C#中则翻译为:GetWindowLong(handle,-16)&(~0xC00000),handle是指要调用的Delphi窗体的句柄,GetWindowLong这个函数是获得该窗体的相关信息。大体上是这个用法,如有不懂大家可以提出来 共同探讨。

一般类型对应如下:

  Dephi-->C#

  intger -->int

  longint -->long

  pchar -->string

  THandle -->IntPtr

C#调用Delphi的dll之详解的更多相关文章

  1. delphi中DLL编程详解

    10.1 Windows的动态链接库原理 动态链接库(DLLs)是从C语言函数库和Pascal库单元的概念发展而来的.所有的C语言标准库函数都存放在某一函数库中,同时用户也可以用LIB程序创建自己的函 ...

  2. vc中调用Com组件的方法详解

    vc中调用Com组件的方法详解 转载自:网络,来源未知,如有知晓者请告知我.需求:1.创建myCom.dll,该COM只有一个组件,两个接口:   IGetRes--方法Hello(),   IGet ...

  3. Python3调用C程序(超详解)

    Python3调用C程序(超详解) Python为什么要调用C? 1.要提高代码的运算速度,C比Python快50倍以上 2.对于C语言里很多传统类库,不想用Python重写,想对从内存到文件接口这样 ...

  4. Delphi XE4 TStringHelper用法详解

    原文地址:Delphi XE4 TStringHelper用法详解作者:天下为公 Delphi XE4的TStringHelper,对操作字符串进一步带来更多的方法,估计XE5还能继续用到. Syst ...

  5. php调用C代码的方法详解和zend_parse_parameters函数详解

    php调用C代码的方法详解 在php程序中需要用到C代码,应该是下面两种情况: 1 已有C代码,在php程序中想直接用 2 由于php的性能问题,需要用C来实现部分功能   针对第一种情况,最合适的方 ...

  6. c#(winform)环境下使用动态链接库dll的详解

    1,什么是dll文件? DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型.在Windows中,许多应用程序并不是一个完整的可执行文件,它们被 ...

  7. c++DLL编程详解

    DLL(Dynamic Link Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了“无库-静态链接库-动态链接库”的时代. ...

  8. 分享一次C#调用Delphi编写Dll程序

    1.前言: 最近接手了一个项目需要和Delphi语言编写的一个系统进行一些接口的对接,数据在传输过程中采用Des加密方式,因为Delphi 平台的加密方式和C#平台的加密方式不互通,所以采用的方式是C ...

  9. Delphi常用关键字用法详解

    本文详细介绍了Delphi中常用的各个关键字名称及用法,供大家在编程过程中借鉴参考之用.详情如下: absolute: ? 1 2 3 4 5 6 7 8 9 10 //它使得你能够创建一个新变量, ...

随机推荐

  1. opencv 中affine函数实现旋转和平移

    图像旋转和平移是图像处理中常用的一种操作,opencv2和opencv3中对图像的旋转和平移都是通过仿射变换函数cv::warpAffine()来实现的. 1.图像的旋转 图像的旋转具体实现分为两步: ...

  2. 2013Hulu校园招聘笔试题

    填空题:1.中序遍历二叉树,结果为ABCDEFGH,后序遍历结果为ABEDCHGF,先序遍历结果为?  FCBADEGH  如下图所示: 2.对字符串HELL0_HULU中的字符进行二进制编码,使得字 ...

  3. 给data设置数据

    console.log(JSON.stringify(that.data.navigator[0].content) + "--____+" + JSON.stringify(th ...

  4. Tomcat数据源总结

    一.数据源的由来   JDBC操作主要由以下几步组成: (1)Class.forName(); (2)Connection con  = DriverManager.getConnection(); ...

  5. Hbase框架原理及相关的知识点理解、Hbase访问MapReduce、Hbase访问Java API、Hbase shell及Hbase性能优化总结

    转自:http://blog.csdn.net/zhongwen7710/article/details/39577431 本blog的内容包含: 第一部分:Hbase框架原理理解 第二部分:Hbas ...

  6. USB2.0学习笔记连载(十八):keil实现寄存器的配置及相关函数讲解(二)

    其实之前也有提及过,Cypress公司提供的官方文件和应用手册真的可以解决很多问题.做的也很人性化,操作也及其简单,几乎只要在 TD_int()里面配置一些常用的参数即可,其他都可以不用操作. 作为一 ...

  7. 关于Unity中旧版动画系统的使用

    Unity在5.X以后,有一个旧版的动画系统和新版的动画系统. 新版的动画系统是使用Unity动画编辑器来调的,调动画和控制动画 旧版的动画系统是用其他的第三方软件调好后导出到一个FBX文件里面,就是 ...

  8. MySQL 数据库 varchar 到底可以存多少个汉字,多少个英文呢?我们来搞搞清楚

    一.关于UTF-8 UTF-8 Unicode Transformation Format-8bit.是用以解决国际上字符的一种多字节编码. 它对英文使用8位(即一个字节) ,中文使用24位(三个字节 ...

  9. 【1】JVM-内存模型

    本篇其实就是一个读书笔记,书是<深入理解JAVA虚拟机>,在网上搜索JAVA内存,说的比较好的其实很多都源自这本书,作为一个JAVA程序员,理解虚拟机是通向高级程序员的必经道路.本篇中的图 ...

  10. 一个hadoop hdfs put 文件失败的小情况

    /root/abc sudo -u hdfs hdfs dfs -put abc /user/larry 然而,提示“put: `abc': No such file or directory”. 一 ...