【发布时间】:2014-01-27 05:52:37
【问题描述】:
我有这种情况,我需要在 .Net 中创建一个可以从 delphi 程序调用的非托管 DLL。我一直在做一些研究,发现了 Robert Giesecke 的图书馆 (RGiesecke.DllExport)。我从一个非常简单的 DLL 开始,它显示一个带有文本框的 windows 窗体,如下所示:
[ComVisible(true)]
[DllExport("PlaceOrder", CallingConvention = CallingConvention.StdCall)]
public static IntPtr PlaceOrder(IntPtr lnpInXml)
{
string inputXml = Marshal.PtrToStringAnsi(lnpInXml);
StringBuilder sbOutputXml = new StringBuilder();
Form1 pti = new Form1(inputXml, sbOutputXml);
pti.ShowDialog();
return Marshal.StringToHGlobalAnsi(sbOutputXml.ToString());
}
这很好用,我设置了 delphi 程序来调用我的 dll,它运行得很好。当我在解决方案中添加对另一个项目的引用并在该项目中创建对象的实例时,问题就出现了。此时,delphi 程序停止显示表单,就像找不到导出的函数一样,但它也不会抛出任何错误:
using MyCommonCode;
namespace UnmanagedDLLTest
{
[ComVisible(true)]
public static class UnmanagedDLL
{
[ComVisible(true)]
[DllExport("PlaceOrder", CallingConvention = CallingConvention.StdCall)]
public static IntPtr PlaceOrder(IntPtr lnpInXml)
{
string inputXml = Marshal.PtrToStringAnsi(lnpInXml);
StringBuilder sbOutputXml = new StringBuilder();
Form1 pti = new Form1(inputXml, sbOutputXml);
pti.ShowDialog();
MyCommonCode.MyClass mc = new MyCommonCode.MyClass();
return Marshal.StringToHGlobalAnsi(sbOutputXml.ToString());
}
}
}
这一行:
MyCommonCode.MyClass mc = new MyCommonCode.MyClass();
是我的问题的根源,只要我评论它,一切都会恢复正常。我一直在谷歌上寻找这样的例子,但我发现的一切都与我的第一段代码相似。在这一点上,任何想法都会非常感激,我开始认为这是不可能的:(。
问候。
【问题讨论】:
-
[ComVisible(true)] 不是必需的。你确定这个另一个 .dll 被复制到 delphi 程序试图加载你的程序集的同一个文件夹中吗?
-
在这种情况下您不能忽略异常,Delphi 代码没有机会告诉您 C# 代码崩溃的原因。当然,根本问题是它找不到包含 MyClass 的 DLL。但这只是一个猜测,专注于 C# 代码本身内部更好的错误处理。使用 try/catch 和一些方法来显示或记录异常。顺便说一句,真的 使用 [ComVisible] 属性会让您领先一步,Delphi 很好地支持 COM,您将有办法诊断和报告错误。
-
感谢您的想法。这是我停止工作时的第一个想法,所以我将所有 dll 移动到 delphi 程序正在寻找初始 dll 的同一文件夹中(它仍然没有工作)。我将尝试将 Nlog 添加到该方法中以将任何异常存储在文件中。如果这不起作用,我会尝试 COM。
-
COM 无能为力。您受主机应用程序界面的约束。 UnmanagedExports 是一个很好的解决方案。实际上,我会尝试使用您用 C++ 或 Python 从头开始编写的不同主机。证明 Delphi 应用程序如您所想的那样工作。还可以尝试调试托管应用程序。单步执行,看看是否引发了异常。