公司有个很古老的系统,代码量很大,并且稳定线上运行10几年,这系统是公司的核心,公司收入基本靠它,系统几乎都是Delphi 7写的,要重写是不可能的。因为Delphi 7编译出来的DLL默认的导出符号就是二进制稳定的C符号。

所以,理论上任何语言都可以调用该DLL导出的API。

值得注意的是,在调用导出API的时候任何语言都是利用LoadLlibrary,GetProcAddress的原理来进行调用的。如果用C++来调用,最好这个干。

调用该API的输入输出参数最好要是平坦内存结构,比如C语言类型的结构体,注意结构体字段与Delphi的导出的结构体的字段长度对应一致。

如果是C#,最后用Marshal相关的函数对参数对象进行转换成平台内存结构来做输入输出,这样才能保证不出错。

如果用C# ,以下是代码参考:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices; namespace CSharpCallDelphiDLL
{
class Program
{ [StructLayout(LayoutKind.Sequential)]
public struct PReadPatientInfoIn
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] Xmlin;
} [StructLayout(LayoutKind.Sequential)]
public struct PReadPatientInfoOut
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] Xmlout;
} [StructLayout(LayoutKind.Sequential)]
public struct PErrorInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public byte[] ErrorXml;
} [DllImport(@"C:/Users/MathxH/Desktop/CSharpCallDelphiDLL/CSharpCallDelphiDLL/bin/x86/Debug/Hisint.dll",
EntryPoint = "ReadPatientInfo", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
extern static void ReadPatientInfo(ref PReadPatientInfoIn pIn, ref PReadPatientInfoOut pOut, ref PErrorInfo pErr); static void Main(string[] args)
{
Console.WriteLine("Enry"); PErrorInfo err;
PReadPatientInfoIn sss;
PReadPatientInfoOut ooo; String kk = "<ROOT><HOSPITALCODE>0003</HOSPITALCODE><PERSONNO></PERSONNO><ARRANGER>陈哈哈</ARRANGER><SECTIONNAME>骨科</SECTIONNAME><ZFLB>11</ZFLB><MZZDMC>癌症</MZZDMC><IDENTIFYNO>532625194704222925</IDENTIFYNO><MSGNO>71</MSGNO></ROOT>"; String emm = ""; Encoding gb2312; System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
gb2312 = Encoding.GetEncoding("GB2312");
Byte[] bytes = gb2312.GetBytes(kk.PadRight());
sss.Xmlin = bytes;
// sss.Xmlin = PadRightEx(kk,4002).ToCharArray(); ooo.Xmlout = encoding.GetBytes(emm.PadRight());
err.ErrorXml = encoding.GetBytes(emm.PadRight()); ReadPatientInfo(ref sss, ref ooo, ref err); // String outss = new String(ooo.Xmlout);
String outss = gb2312.GetString(ooo.Xmlout); Console.ReadLine(); }
}
}

以上代码期间出了一些错误:

1. 抛出BadImageFormatException的异常,也就是exe的代码要与所调用的DLL的机器位数一致,x86只能调用x86的,x64只能是x64.

2. 未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配。 这个需要C#这边的array长度与声明的长度一致,需要Padding补齐

3.    System.Runtime.InteropServices.COMException”类型的未经处理的异常在 CSharpCallDelphiDLL.exe 中发生
传递给系统调用的数据区域太小。 (异常来自 HRESULT:0x8007007A)。这个是PadRight的时候出现中文编码导致填充的长度出现问题。把中文改成英文就不会出错了。
4. 针对问题3,因为参数肯定会有中文,所以,需要把编码转换成GB2312 locale

references:

https://www.cnblogs.com/wintalen/archive/2010/12/20/1911599.html

https://blog.csdn.net/cnhk1225/article/details/53265042

http://blog.51cto.com/andwp/1352739

https://www.cnblogs.com/Robert-huge/p/5130284.html

http://www.myexception.cn/h/1381235.html

VS2017写的exe调用Delphi 7写的DLL的更多相关文章

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

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

  2. 用delphi的THTTPRIO控件调用了c#写的webservice。

    用delphi的THTTPRIO控件调用了c#写的webservice. 下面是我调试时遇到的一些问题: 1,导入wsdl文件:file--new----other----wenservice---W ...

  3. Delphi XE3写DLL,用Delphi7调用,报错!

    http://bbs.csdn.net/topics/390870532 用delphi xe3写的DLL,delphi7调用,参数都是PAnsiChar,DLL里的函数接收delphi7传的入参,没 ...

  4. 新奇:(nodejs兄弟)用HTML + FLASH +JS 也可以写桌面EXE。

    首先看下面这张图片,下面的所有界面都是用html代码实现的. 编程IDE:vb6.0 使用控件:WEBBROWSER 原理:使用olelib 让程序继承:IDocHostUIHandler 和 ICu ...

  5. JAVA调用C语言写的SO文件

    JAVA调用C语言写的SO文件 因为工作需要写一份SO文件,作为手机硬件IC读卡和APK交互的桥梁,也就是中间件,看了网上有说到JNI接口技术实现,这里转载了一个实例 // 用JNI实现 // 实例: ...

  6. (转载)将DELPHI数据库连接写进INI配置文件中

    将DELPHI数据库连接写进INI配置文件中 procedure TDM.DataModuleCreate(Sender: TObject); var piececonfg:Tinifile; pat ...

  7. java调用C/C++写的dll(转)

    源:java调用C/C++写的dll Java语言本身具有跨平台性,如果通过Java调用DLL的技术方便易用,使用Java开发前台界面可以更快速,也能带来跨平台性. Java调用C/C++写好的DLL ...

  8. 关于 php 调用 其他语言写的Web Service SOAP 接口的参数传递问题

    关于 php 调用 其他语言写的Web Service SOAP 接口的参数传递问题,有需要的朋友可以参考下. php调用java写的soap接口经验:   场景一: java是以数组的形式接收参数的 ...

  9. 更改开机默认不显示explorer.exe,直接启动自己写的EXE程序方法

    原文:更改开机默认不显示explorer.exe,直接启动自己写的EXE程序方法 更改开机默认不显示explorer.exe,直接启动自己写的EXE程序的函数: bool UpdateWinlogon ...

随机推荐

  1. SharePoint 2013 开启访问请求 链接丢失

    关于SharePoint 2013 开启访问请求的做法其实很简单,比如http://www.cnblogs.com/jianyus/archive/2014/06/21/3799386.html 这篇 ...

  2. mysql分布式数据库中间件对比

    目前数据库中间件有很多,基本这些中间件在下都有了解和使用,各种中间件优缺点及使用场景也都有些心的.所以总结一个关于中间件比较的系列,希望可以对大家有帮助. 1. 什么是中间件 传统的架构模式就是 应用 ...

  3. .Net程序员玩转Android开发--ListView单击事件

    public class ListViewClickActivity extends Activity {         private ListView lv;        SimpleAdap ...

  4. 【转】Linux基础与Linux下C语言编程基础

    原文:https://www.cnblogs.com/huyufeng/p/4841232.html ------------------------------------------------- ...

  5. JPA(二):HellWord工程

    使用JPA持久化对象的操作步骤: 1)创建persistence.xml,在这个文件中配置持久化单元: --- 需要指定跟哪个数据库进行交互: --- 需要指定JPA使用哪个持久化的框架以及配置该框架 ...

  6. maven多module项目中千万不要引入其它模块的单元測试代码

    本文出处:http://blog.csdn.net/chaijunkun/article/details/35796335,转载请注明. 因为本人不定期会整理相关博文,会对对应内容作出完好. 因此强烈 ...

  7. IDEA 禁止自动导入引用包 取消import包

    http://www.oschina.net/question/2010061_226765 我想拷贝一小段代码,或者我就是不想引入拷贝来的包,我该怎么取消掉idea的自动导入import包呢? 找到 ...

  8. linux 安装elasticsearch 可能遇到的问题

    1.can not run elasticsearch as root 切换到非root用户 因为安全问题elasticsearch 不让用root用户直接运行,所以要创建新用户 第一步:liunx创 ...

  9. 给ajax表单提交数据前面加上实体名称

    有时候我们后台做了一个引用类型例如: 下面的实体以C#为例 public class Order{ public string orderId{get;set;} public OrderItem o ...

  10. C#.NET常见问题(FAQ)-如何让Listbox支持多选

    把SelectionMode改成MultiExtended   更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com/acetaohai123   我的在线 ...