从 Delphi 7 中的 C++ DLL 接收字符串数组

2024-03-29

我正在用 C++ 创建一个 DLL,它将在 Delphi 7 项目中使用。

这个问题与this one https://codereview.stackexchange.com/questions/43347/produce-an-array-of-strings-from-a-single-string/43398?noredirect=1#43398,我在这里展示两个函数Validate and GetToken只是现在它们将在 C++ 和字符串数组中完成GetToken产品将被送回德尔福。

问题是我不知道如何在 dll 中创建将返回 c++ 中的字符串数组的函数,并且我不知道如何存储它以供在 Delphi 中进一步使用。

函数的声明如下:

function GetToken(Chain:string):Arrayofstring;


根据您的代码审查,Delphi 代码期望该函数具有以下签名:

function GetToken(Chain: AnsiString): array of AnsiString;

你不能用 C++ 编写这样的函数。 C++ 不知道 Delphi 字符串是什么,也不知道 Delphi 动态数组是什么。这两种类型都需要从 Delphi 的内存管理器分配,而您的 C++ DLL 无法访问该内存管理器。此外,C++不知道如何使用Delphi的register调用约定。

DLL接口设计得很糟糕。 DLL 永远不应该使用特定于语言的类型,除非它是设计者的意图排除所有其他语言。 (在这种情况下,甚至同一语言的更高版本也被排除在外,因为AnsiStringDelphi 2009 中进行了更改,以包含更多 Delphi 7 无法正确处理的元数据。)选择的最安全的调用约定通常是stdcall。 Windows API 中的所有内容都使用它。

更好的接口将使用所有语言通用的类型,并且它将规定使用可普遍访问的内存管理。有几种常见的方法可以做到这一点。例如:

  • 字符串作为简单的以 null 结尾的字符数组返回 -PAnsiChar在德尔福;char*在C++中。 DLL 为字符串分配缓冲区,并为这些字符串的数组分配缓冲区。当主机应用程序完成使用数组和字符串时,它调用 DLL 导出的另一个函数,其中 DLL 释放它分配的内存。例如,这是使用的模型,FormatMessage http://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx;当主机程序完成消息字符串时,它调用LocalFree.

    type
      PStringArray = ^TStringArray;
      TStringArray = array[0..Pred(MaxInt) div SizeOf(PAnsiChar)] of PAnsiChar;
    function GetToken(Char: PAnsiChar): PStringArray; stdcall;
    procedure FreeStringArray(StringArray: PStringArray); stdcall;
    
    char** __stdcall GetToken(char const* Chain);
    void __stdcall FreeStringArray(char** StringArray);
    
  • 使用 COM 返回 BStr 对象的安全数组。它与之前的技术类似,但内存管理是由 COM 而不是由 DLL 定义的,因此需要由接口双方定义的内容较少。

  • 将回调函数传递给 DLL,因此 DLL 只针对它标识的每个字符串调用该函数一次,而不是返回字符串数组。然后,您不必定义任何数组的样子,并且每个字符串的生命周期可以只是回调调用的生命周期 - 如果主机应用程序想要一个副本,它可以这样做。新的函数签名看起来像这样:

    type
      TTokenCallback = procedure(Token: PAnsiChar); stdcall;
    procedure GetToken(Chain: PAnsiChar; ProcessToken: TTokenCallback); stdcall;
    
    typedef void (__stdcall* TokenCallback)(char const* Token);
    void __stdcall GetToken(char const* Chain, TokenCallback ProcessToken);
    

如果您不是设计 DLL 接口的人,那么您需要向设计者求助并对其进行更改,以便非 Delphi 代码更容易访问。如果您做不到这一点,那么最后的替代方案是在 Delphi 中编写一个 DLL,将您的 DLL 包装起来,以将参数调整为双方都能理解的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Delphi 7 中的 C++ DLL 接收字符串数组 的相关文章

  • binary_log_types.h:没有这样的文件或目录

    我正在编译一个小型 mysql C 项目并且 遇到以下错误 C Program Files x86 MySQL MySQL Server 5 7 include mysql com h 22 30 fatal error binary lo
  • 为什么这个 oracle 批量插入不起作用?

    我正在尝试将一些数据批量插入到 oracle 数据库中 我按照文档中的示例进行操作 this DataBaseAccess new OracleConnection connString var dataAdapter new Oracle
  • 比较 LINQ to SQL 中的两个日期

    我有一个数据库 其中有一个名为会议的表 会议日期使用以下格式存储在此表中 May 2nd 2011 例如 格式为5 2 2011 我的要求是获取两个日期 例如 2011 年 4 月 25 日和 2011 年 5 月 2 日 之间的会议 并编
  • 如何在 scala 中的二维数组上使用 contains 方法

    我有一个二维数组 我想检查二维数组内是否存在数组 我努力了 var arr Array Array 2 1 Array 4 3 var contain arr contains Array 4 3 println contain 这应该打印
  • 试图使用加密来混淆我的项目打破了它

    我试图尝试不同的混淆选项 为了做到这一点 我首先尝试了加密货币 以下是我遵循的步骤 打开加密向导并选择一些选项 选择我的解决方案文件 完成向导后 我看到有些 Dll 被很好地混淆了 但我的项目现在无法构建 我注意到的两件事是 我的文件夹中有
  • 如何删除实体框架6中的多对多关系

    如果将项目连接为多对多关系 则从数据库中删除项目时会出现问题 我的数据库看起来像 Project lt JobInProject gt Job ProjectID JobInProjectID JobID ProjectID JobID 主
  • Identity Server 4:添加访问令牌的声明

    我正在使用 Identity Server 4 和隐式流 并且想要向访问令牌添加一些声明 新的声明或属性是 tenantId 和 langId 我已将 langId 添加为我的范围之一 如下所示 然后通过身份服务器请求 但我也获得了tena
  • 为什么这个单独的定义会导致错误?

    挑战 我有这段代码无法编译 你能找出问题所在吗 有一次让我很头疼 header namespace values extern std string address extern int port cpp file std string v
  • 除空字符串外的任何内容的正则表达式

    是否可以使用正则表达式来检测任何不是 空字符串 的内容 如下所示 string s1 string s2 string s3 string s4 etc 我知道我可以使用修剪等 但我想使用正则表达式 s 将匹配任何包含至少一个非空格字符的字
  • 将授权标头添加到 Web 参考

    我正在尝试向客户端的网络服务发出请求 我不知道客户端的底层平台 我使用 添加 Web 引用 在 Visual Studio 2010 中使用了客户端的 WSDL 并生成了我的代理类 称为 ContactService 我现在需要将如下所示的
  • 为什么我无法调试动态加载的程序集?

    我正在开发一个 Web API 项目 该项目使用内部模拟框架 允许拦截和修改来自控制器的响应 它使用 MEF 加载包含某些先决条件匹配时执行的代码的程序集 我知道这是正常工作的 因为我可以在响应中看到模拟已被执行 但由于某种原因我无法调试动
  • 类型别名和不完整类型

    我可能已经超出了解决这个本应简单的问题的范围 我在这里开始这个问题 在编译时获取基类的类型 https stackoverflow com questions 17735852 getting type of a base class at
  • 为什么必须通过 this 指针访问模板基类成员?

    如果下面的类不是模板 我可以简单地拥有x in the derived班级 但是 通过下面的代码 我have to use this gt x Why template
  • C++ 联合数组和变量?

    在C 中没有办法做这样的事情吗 union Scalar x y Scalar v 2 Where x v 0 and y v 1 既然您使用的是 C 而不是 C 并且它们具有相同的类型 为什么不直接将 x 设为对 v 0 的引用 将 y
  • 如何组合||条件语句中的运算符[重复]

    这个问题在这里已经有答案了 代替 if foo 1 foo 5 foo 9 我喜欢将它们组合起来 类似于以下内容 这不起作用 if foo 1 5 9 那可能吗 不幸的是不是 你最好的选择是创建一个扩展方法 public static bo
  • 如何创建和使用类箭头运算符? [复制]

    这个问题在这里已经有答案了 因此 在到处研究之后 我似乎找不到如何创建类箭头运算符 即 class Someclass operator gt 我只需要知道如何使用它并正确使用它 它的输入是什么 它返回什么 我如何正确地声明 原型化它 运算
  • 返回 ICollection 而不是 List 的真正优势是什么? [复制]

    这个问题在这里已经有答案了 我读过几篇博客文章 提到对于公共 API 我们应该始终返回 ICollection 或 IEnumerable 而不是 List 返回 ICollection 而不是 List 的真正优势是什么 Thanks 复
  • C# 3.0 中自动属性和公共字段的区别

    我无法理解为什么 C 3 0 中存在自动实现的属性语言功能 当你说的时候有什么区别 public string FirstName than public string FirstName get set 因为它们在生成的 IL 代码 和机
  • 用于 nmap 输出的 C++ xml 解析器

    我是 nmap 的新手 我在 nmap 教程中看到 https nmap org book man output html https nmap org book man output html oX 选项可用于获取 xml 格式的 nma
  • asp.net mvc GET 请求上的 formcollection 应该为空

    我正在发布一个简单的操作 public void Login FormCollection formCollection 即使查询字符串值很少 formcollection Count is 0 是靠行为吗 FormCollection 使

随机推荐

  • 从超类 static main 创建子类

    我有一个通用的抽象类 SuperClass 我想要有一个main方法 这将是每个子类的默认 main 方法 并且会执行相同的操作 但具有派生并调用它的正确子类对象 像这样 public abstract class SuperClass s
  • 错误:行太大:大小 8168,最大大小 8164

    我正在使用 PostgreSql 9 2 我有很多角色 并且所有角色都被授予了模式的 USAGE 权限 当我尝试创建新用户并授予权限时 我收到错误 CREATE ROLE my user GRANT USAGE on schema my s
  • 如何检查 PHP 是否打开了端口 465 和 587?

    我正在尝试使用 PHPMailer 通过 SMTP 和 gmail 发送电子邮件 我使用的确切脚本适用于其他服务器 但不适用于该特定托管公司的服务器 我已经检查过phpinfo 它告诉我allow url fopen is on并且没有di
  • 寻求有关以最小的开销在 Netflix Eureka 可发现的 Spring Boot 服务上进行开发的正确方法的建议

    我们正在运行一个基于 Spring Boot 的环境 其中包含大约 15 个微服务和一个注册到 Eureka 的 Zuul 边缘网关 目前 我已经设置了所有微服务通过 Zuul 网关调用其他微服务 例如 如果 serviceA 需要调用 s
  • 带接收器的 Kotlin 函数参数,从 Groovy 调用

    Kotlin 和 Groovy 都提供了一种编写高阶函数的方法 其中函数参数具有隐式接收器 科特林版本 class KotlinReceiver fun hello println Hello from Kotlin class Kotli
  • 如果值为 null,则在提交之前使用 js 或 jQuery 更改输入文本值

    如果输入值为 null 如何在提交之前使用 js 或 jQuery 更改输入文本值 感谢帮助 With jQuery http jquery com 您可以使用以下命令将回调绑定到提交事件 submit http api jquery co
  • 为什么我应该始终启用编译器警告?

    我经常听说在编译 C 和 C 程序时我应该 始终启用编译器警告 为什么这是必要的 我怎么做 有时我也听说我应该 将警告视为错误 我是不是该 我怎么做 为什么我应该启用警告 众所周知 C 和 C 编译器不善于报告一些常见的程序员错误默认情况下
  • Capybara 无法识别动态添加的 DOM 元素?

    在使用 Capybara 和 Selenium 时 我似乎在测试使用 jQuery 执行的 javascript 操作时遇到了麻烦 预期的行为是当用户单击链接 添加资源 时动态生成表单 Capybara 将能够单击该链接 但无法识别新的表单
  • Greasemonkey:新更新中“未定义 GM_xmlhttpRequest”

    为什么这个简单的 Greasemonkey 脚本对我不起作用https jsfiddle net pghnsw8z 1 https jsfiddle net pghnsw8z 1 我的意思是 在进行 ajax 调用时 我没有得到成功的响应
  • 无需表单即可在屏幕上绘图

    是否可以在不使用表单应用程序的情况下在屏幕上创建一个大的白色矩形 如果可能的话 它应该覆盖整个屏幕 我知道我必须使用System Drawing并尝试了几个步骤 但没有一个真正在我的屏幕上打印任何内容 方法一 调用Windows API 你
  • ANDROID从url获取内容

    我在使用 Android 时遇到问题 我必须能够从生成内容的 URL 中读取内容 然后将它们放入数组中 分割读取的字符串 我使用了不同的方法 但无法读取该字符串 我能怎么做 这是我现在使用的函数 继续出现字符串 nn va private
  • 具有可比较列表与 TreeSet

    选项 1 创建一个实现 Comparable 的列表 并在每次添加值时使用 collections sort List l 对它进行排序 选项 2 创建一个 TreeSet 它始终保持排序 哪一个会更快 我问这个是因为 List 为我提供了
  • git am 错误:“补丁不适用”

    我正在尝试使用 git 将多个提交从一个项目移动到第二个类似的项目 所以我创建了一个补丁 包含 5 个提交 git format patch 4af51 stdout gt changes patch 然后将补丁移动到第二个项目的文件夹并想
  • 如何在 C# 中使用 SendMessageTimeout 获取窗口标题

    我需要枚举所有打开的窗口并获取它们的标题 但问题是某些窗口属于同一进程但属于不同的线程 该线程被阻塞 等待互斥体 因此 我不能对属于我自己的进程的窗口使用 GetWindowText 因为这将导致 SendMessage 调用 这将阻止我的
  • 向类型类实例添加类约束

    我正在尝试实现康托配对函数 作为 通用 Pair 类型类 如下所示 module Pair Pair CantorPair where Pair interface class Pair p where pi a gt a gt p a k
  • 如何使用 C++ 从 RAM 运行可执行文件?

    如何使用 C 从 RAM 运行可执行文件 可执行文件位于 RAM 中 并且我知道地址 如何从我的程序中调用该程序 这类事情通常来自世界的黑暗角落 结合像metasploit这样的工具 用内存创建进程会很棒 因此一些人尝试重新实现Create
  • 向应用程序小部件发送更新广播

    我有一个带有配置活动的应用程序小部件 我想在单击活动中的 确定 按钮时触发小部件的更新 我写了这段代码 Intent initialUpdateIntent new Intent AppWidgetManager ACTION APPWID
  • 为什么 firefox/chrome 显示的页面与 IE8 不同?

    当我看着 我看到最新版本 with Firefox and Chrome 但是一个旧版本 with IE8 另外 通过屏幕抓取PHP Curl给我一个旧版本 我试过了CTRL 刷新在 IE8 中 但我无法让它向我显示最新版本 无论heade
  • 警告:格式字符串不是字符串文字[重复]

    这个问题在这里已经有答案了 我从以下行收到 格式字符串不是字符串文字 警告 NSString formattedString NSString alloc initWithFormat format arguments valist 我在以
  • 从 Delphi 7 中的 C++ DLL 接收字符串数组

    我正在用 C 创建一个 DLL 它将在 Delphi 7 项目中使用 这个问题与this one https codereview stackexchange com questions 43347 produce an array of