tStringList 将 C# 传递给 Delphi DLL

发布于 2024-07-06 23:15:14 字数 467 浏览 7 评论 0原文

我有一个 Delphi DLL,其函数定义为:

function SubmitJobStringList(joblist: tStringList; var jobno: Integer): Integer;

我从 C# 调用它。 如何将第一个参数声明为 C# 中不存在的 tStringList。 我目前的声明为:

[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);

但是当我调用它时,我收到内存访问冲突异常。

有人知道如何从 C# 正确传递到 tStringList 吗?

I have a Delphi DLL with a function defined as:

function SubmitJobStringList(joblist: tStringList; var jobno: Integer): Integer;

I am calling this from C#. How do I declare the first parameter as a tStringList does not exist in C#. I currently have the declaration as:

[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);

But when I call it I get a memory access violation exception.

Anyone know how to pass to a tStringList correctly from C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

波浪屿的海角声 2024-07-13 23:15:14

你很可能不会有任何运气。 TStringList 不仅仅是一个数组,它是一个成熟的类,并且确切的实现细节可能与 .NET 的实现细节有所不同。 看一下 Delphi VCL 源代码(如果你有的话)并尝试找出是否可以用 C# 重建该类,并在你最好的朋友 Interop Marshaller 的帮助下通过它。 请注意,即使 Delphi 字符串类型与 .NET 字符串类型不同,并且在不告诉编组器应该做什么的情况下传递它,他很可能会将其作为字符数组传递。

除此之外,我建议更改 Delphi DLL。 在供非 Delphi 客户端使用的 DLL 中公开任何特定于 Delphi 的内容从来都不是一件好事。 将参数设置为 PChar 数组,应该没问题。

You'll most likely not have any luck with this. The TStringList is more than just an array, it's a full-blown class, and the exact implementation details may differ from what is possible with .NET. Take a look at the Delphi VCL source code (that is, if you have it) and try to find out if you can rebuild the class in C#, and pass it with the help of your best friend, the Interop Marshaller. Note that even the Delphi string type is different from the .NET string type, and passing it without telling the marshaller what he should do, he will pass it as a char-array, most likely.

Other than that, I would suggest changing the Delphi DLL. It's never a good thing to expose anything Delphi-specific in a DLL that is to be used by non-Delphi clients. Make the parameter an array of PChar and you should be fine.

梦情居士 2024-07-13 23:15:14

如果这是您的 DLL,我会重写该函数以接受字符串数组。 避免将类作为 DLL 参数传递。

或者,如果您出于某种原因确实想要使用 TStringList,则可以从任何 .Net 语言中使用 Delphi 的 VCL.Net。

使用 TIniFile 的旧示例: http://cc.codegear.com/Item/22691

该示例在 Delphi 2005 中使用 .Net 1.1。Delphi 2006 和 2007 支持 .Net 2.0。

If this is your DLL, I'd rewrite the function to accept an array of strings instead. Avoid passing classes as DLL parameters.

Or, if you really want to use a TStringList for some reason, Delphi's VCL.Net can be used from any .Net language.

An old example using TIniFile: http://cc.codegear.com/Item/22691

The example uses .Net 1.1 in Delphi 2005. Delphi 2006 and 2007 support .Net 2.0.

撞了怀 2024-07-13 23:15:14

如果您不控制 DLL,并且他们不能或不会更改它,您始终可以在单独的 DLL 中编写自己的 Delphi 包装器,并使用跨语言更友好的参数。

将类作为 DLL 函数的参数确实是一种不好的形式。

If you don't control the DLL and they can't or won't change it, you could always write your own Delphi wrapper in a separate DLL with parameters that are more cross-language friendly.

Having a class as a parameter of a DLL function really is bad form.

|煩躁 2024-07-13 23:15:14

我不太清楚你使用 delphi 和 C# 的方式。 您似乎已经创建了一个想要从 C# 调用的 Win32 DLL。 当然,您必须为此使用 PInvoke。

我建议您使用源代码创建一个 .NET DLL,因为 VCL 的完整移植是可用的。 如果您愿意,我可以进一步详细说明......

I am not exactly clear your way of using delphi and C#. It seems you have created a Win32 DLL which you want to call from C#. Offcourse you must be using PInvoke for this.

I would suggest that you create a .NET DLL using your source code since complete porting of VCL is available. I can further elaborate if you wish....

贪了杯 2024-07-13 23:15:14

理论上,您可以通过使用指针(将它们转换为 C# IntPtr 类型)而不是强类型对象引用(或者可能将它们包装在其他类型中以避免必须声明不安全块)来执行类似的操作),但最重要的问题是:Delphi 运行时必须是为对象分配和释放内存的机制。 为此,您必须在 Delphi 编译的 DLL 中声明调用 TStringList 类的构造函数和析构函数的函数,必须确保 Delphi DLL 使用 ShareMem 单元,并且必须负责递增和递减引用计数在离开 DLL 之前和进入 DLL 之后,最好也作为从 Delphi DLL 导出的函数。

简而言之,这是一项大量工作,因为您必须在同一个进程中处理两个内存管理器(.NET CLR 和 Delphi 的分配器),并且您必须手动管理内存 “愚弄”Delphi 内存管理器和运行时。 您必须采用此设置有什么特殊原因吗? 您能描述一下您试图在更高层次上解决的问题吗?

In theory, you could do something like this by using pointers (casting them as the C# IntPtr type) instead of strongly typed object references (or perhaps wrapping them in some other type to avoid having to declare unsafe blocks), but the essential catch is this: The Delphi runtime must be the mechanism for allocating and deallocating memory for the objects. To that end, you must declare functions in your Delphi-compiled DLL which invoke the constructors and destructors for the TStringList class, you must make sure that your Delphi DLL uses the ShareMem unit, and you must take responsibility for incrementing and decrementing the reference count for your Delphi AnsiStrings before they leave the DLL and after they enter it, preferably also as functions exported from your Delphi DLL.

In short, it's a lot of work since you must juggle two memory managers in the same process (the .NET CLR and Delphi's allocators) and you must both manage the memory manually and "fool" the Delphi memory manager and runtime. Is there a particular reason you are bound to this setup? Could you describe the problem you are trying to solve at a higher level?

咽泪装欢 2024-07-13 23:15:14

正如 Hemant Jangid 所说,通过将代码编译为 .NET dll,然后在 c# 项目中引用该程序集,您应该能够轻松地做到这一点。

当然,只有当您拥有的 Delphi 版本具有 Delphi.NET 时,您才能执行此操作。

As Hemant Jangid said, you should easily be able to do this by compiling your code as a .NET dll and then referring to that assembly in your c# project.

Of course, you'll only be able to do this if the version of Delphi you have has Delphi.NET.

幽梦紫曦~ 2024-07-13 23:15:14

我对 C# 了解不多,但我用于跨上下文传输字符串列表的技术是使用 .text 属性来获取表示列表的字符串,然后在“另一侧”分配该属性。

通常更容易将一根绳子穿过墙壁,因为它是一个成熟的物体。

I don't know a lot about c#, but a technique that I use for transporting stringlists across contexts is using the .text property to get a string representing the list, then assigning that property on "the other side".

It's usually easier to get a string over the wall that it is a full blown object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文