tStringList在C#中传递给Delphi DLL
我有一个Delphi DLL,其函数定义为:
函数SubmitJobStringList(joblist:tStringList; var jobno:Integer):整数;
我是从C#调用的。我如何将第一个参数声明为tStringList在C#中不存在。我目前的声明为:
[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);
但是当我调用它时,我遇到了内存访问冲突异常。
任何人都知道如何从C#正确传递给tStringList吗?
解决方案
我们很可能对此没有任何运气。 TStringList不仅仅是一个数组,它是一个成熟的类,确切的实现细节可能与.NET可能不同。看一下Delphi VCL源代码(也就是说,如果有的话),并尝试找出是否可以用C#重建类,并在最好的朋友Interop Marshaller的帮助下传递它。请注意,即使Delphi字符串类型也不同于.NET字符串类型,并且在不告诉编组者应该做什么的情况下传递它,则很有可能将其作为char数组传递。
除此之外,我建议更改Delphi DLL。在非Delphi客户端使用的DLL中公开任何特定于Delphi的东西从来都不是一件好事。将参数设置为PChar数组,就可以了。
我不清楚我们使用delphi和C#的方式。看来我们已经创建了要从C#调用的Win32 DLL。当然,我们必须为此使用PInvoke。
由于可以完全移植VCL,因此我建议我们使用源代码创建.NET DLL。如果我们愿意,我可以进一步详细说明。
从理论上讲,我们可以通过使用指针(将其广播为CIntPtr类型)而不是强类型的对象引用(或者可能将它们包装为其他类型以避免避免声明不安全的块)来执行类似的操作,但是最重要的是注意:Delphi运行时必须是为对象分配和取消分配内存的机制。为此,必须在Delphi编译的DLL中声明调用TStringList类的构造函数和析构函数的函数,必须确保Delphi DLL使用ShareMem单元,并且必须负责递增和递减引用计数。为Delphi AnsiStrings离开DLL之前以及进入它们之后,最好也作为从Delphi DLL导出的函数。
简而言之,这是很多工作,因为我们必须在同一个进程(.NET CLR和Delphi的分配器)中处理两个内存管理器,并且必须手动管理内存并"愚弄" Delphi内存管理器和运行时。我们是否有特定的理由要绑定到此设置?我们能从更高层次描述我们要解决的问题吗?
正如Hemant Jangid所说,通过将代码编译为.NET dll,然后在cproject中引用该程序集,我们应该可以轻松地做到这一点。
当然,仅当我们拥有的Delphi版本具有Delphi.NET时,我们才能执行此操作。
如果这是DLL,则我将重写该函数以接受字符串数组。避免将类作为DLL参数传递。
或者,如果我们出于某些原因确实想要使用TStringList,则可以从任何.Net语言中使用Delphi的VCL.Net。
使用TIniFile的旧示例:http://cc.codegear.com/Item/22691
该示例在Delphi 2005中使用.Net1.1. Delphi2006和2007支持.Net 2.0。
如果我们不控制DLL并且他们不能或者不会更改它,则可以始终在具有更跨语言友好参数的单独DLL中编写自己的Delphi包装器。
将类作为DLL函数的参数确实是一种不好的形式。
我对c#不太了解,但是我用于跨上下文传输字符串列表的一种技术是使用.text属性获取表示列表的字符串,然后在"另一侧"分配该属性。
通常,将一串绳子吹成一团完整的物体比较容易。