公司有个很古老的系统,代码量很大,并且稳定线上运行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. 数据库实例: STOREBOOK > 用户 > 编辑 用户: SYS

    ylbtech-Oracle:数据库实例: 数据库实例: STOREBOOK  >  用户  >  编辑 用户: SYS 编辑 用户: SYS 1. 一般信息返回顶部 1.1, 1.2, ...

  2. 检索(retrieval && search )-单目标-多目标跟踪-MTMC Tracking和 ReID

    跨摄像头多目标跟踪(Multi-Target Multi-Camera Tracking, MTMC Tracking) 跨摄像头多目标跟踪(Multi-Target Multi-Camera Tra ...

  3. 整合spring cloud云架构 - SSO单点登录之OAuth2.0登录认证(1)

    之前写了很多关于spring cloud的文章,今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一.oauth中的角 ...

  4. C# 二种方法控制系统音量/麦克风大小

    场景:在做播放设备的时候需要控制音量的大小,下面几种方法将满足你的要求 方法一: 改变系统音量设置 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...

  5. 揭秘uc浏览器二

    这节,四个议题: ①一个网页显示在webview控件中 ②如何正常隐藏显示标题栏. ③如何用runnable来隐藏标题栏,这样子就更加的专业化. ④上节我们说道了QuickActionGrid,看他长 ...

  6. POJ 2280 Amphiphilic Carbon Molecules 极角排序 + 扫描线

    从TLE的暴力枚举 到 13313MS的扫描线  再到 1297MS的简化后的扫描线,简直感觉要爽翻啦.然后满怀欣喜的去HDU交了一下,直接又回到了TLE.....泪流满面 虽说HDU的时限是2000 ...

  7. 转: wireshark的使用说明

    原创者:http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html from:  https://mp.weixin.qq.com/ ...

  8. “No module named bs4”问题

    用tushare,import的时候,老报这个错.我的系统是重装的,包都是直接复制过来的.重新安装也不行. 最后,从网上下beautifulsoup4-4.6.0-py2-none-any.whl安装 ...

  9. HDU 1541 Stars (线段树)

     Problem Description Astronomers often examine star maps where stars are represented by points on ...

  10. iOS 获取APP相关信息 私有API

    /* Generated by RuntimeBrowser Image: /System/Library/Frameworks/MobileCoreServices.framework/Mobile ...