公司有个很古老的系统,代码量很大,并且稳定线上运行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. C++中一些类和数据结构的大小的总结

    针对class,虚函数等情况写了一些代码测试. #include <stdio.h> class A { }; class B { public: void f(); void g(); ...

  2. 会动的文字Marquee应用(转)

    想要做个滚动公告,看了网上的教程,无一不是很恐怖的场频啊java语言编制的JS,或者就是各种复杂,无意中发现了Marquee这东西,用了一下,很简单,只需两行代码,即可以实现很好的效果,特此分享一下. ...

  3. 在OneNote中快速插入当前日期和时间

    做笔记,难免有时需要记录当时的时间,记住这个快捷键会让记笔记的效率提升一点. To insert the current date and time, press Alt+Shift+F. To in ...

  4. iOS开发-iOS8地理位置定位

    现在的App基本上都有定位功能,旅游网站根据定位推荐旅游景点,新闻App通过地理位置推荐当地新闻,社交类的App通过位置交友,iOS中实现以上功能需要一个核心的框架CoreLocation,框架提供了 ...

  5. mongodb 按配置文件mongodb.conf启动

    命令如下 mongod --config /etc/mongodb.conf

  6. 25个可遇不可求的jQuery插件

    随着jQuery插件在网站建设过程中的使用率不断的增加,所以有必要跟进时代步伐开发出一些新的插件/代码片段,以此来巩固并提高前端用户体验,将用户体验提升到一个新的高度. 接下来所推荐的这些插件中有滑块 ...

  7. 我对android davilk 虚拟机的理解

    Davilk虚拟机作为Android平台的一部分.Google公司花了大量时间思考针对低功耗手持设备的优化设计.在智能手机出现之前,与桌面设备相比,手持设备在内存和速度方面落后8-10年.它们的计算能 ...

  8. 用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践

    https://zhuanlan.zhihu.com/p/25928551 近来在同时做一个应用深度学习解决淘宝商品的类目预测问题的项目,恰好硕士毕业时论文题目便是文本分类问题,趁此机会总结下文本分类 ...

  9. Centos6.4下安装protobuf-c问题及解决办法

    1.前言 protobuf是Google提供的结构持久化工具,类型XML,但要比XML更加灵活,效率要高.protobuf当初支持C++.JAVA和Python,后来有了支持C语言的Protobuf- ...

  10. Apache+wsgi+flask部署

    flask自带的web server是开发用途,并不适用与发布,需要借助专业的web服务器. 配置的坑无数,Apache部署,403禁止,莫名其妙无法访问,500内部错误把我搞得崩溃了. 重点参考: ...