[英]“ASP.NET web application” and unmanaged DLL
接下来的情况是:我有用Delphi编写的“ .dll”文件。 它获取字符串参数并将其返回。 如果我在“ Windows”的“ C#”应用程序中使用此“ .dll”-可以正常工作,但是我需要在“ asp.net Web应用程序”中使用它,并且在Web应用程序中会生成下一个异常:
iisexpress.exe has triggered a breakpoint.
Unhandled exception at 0x77A9E753 (ntdll.dll) in iisexpress.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77AD4270).
“ asp.net Web应用程序”中的其他非托管“ .dll”文件运行正常。 因此,我使用ShareMem和borlandmm.dll制作了简单的模拟“ .dll”:
library Testas;
uses
ShareMem, SysUtils, Classes;
{$R *.res}
function DllTestas(var InputOutput: PAnsiChar): Longint; stdcall;
begin
Result := StrToIntDef(InputOutput, 0);
InputOutput := 'aaaa';
end;
exports
DllTestas;
begin
end.
和简单的“ asp.net Web应用程序”:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.InteropServices;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
[DllImport("Testas.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern int DllTestas([MarshalAsAttribute(UnmanagedType.AnsiBStr)] ref string InputOutput);
protected void Page_Load(object sender, EventArgs e)
{
string InOut = "123";
int result = DllTestas(ref InOut);
Response.Write("Testas.dll:" + "<br />" + result.ToString() + " " + InOut + "<br />" + "<br />");
}
}
}
属性-检查“本机代码”,“平台目标”为“ x86”。
因此,此模拟代码生成相同的结果。
问题:错误在哪里以及如何解决?
建议将“ .dll”重写为“ C#”-请不要提供。 这是我的第一个主意,但是制作此“ .dll”的人会找到1000个无法实现的原因,因为这是他的“面包”,而他并不是学习新语言的灵感源泉。
模拟文件“ .dll”是用“ Delphi 2005”和“ Delphi XE5”编译的-结果相同。 “ asp.net Web应用程序”-“ VS 2013 Ultimate”。 我有“ .dll”的来源。
function DllTestas(var InputOutput: PAnsiChar): Longint; stdcall;
这个原型注定要失败。 它不能合理地用于互操作。 问题是,不清楚谁分配内存以及谁负责整理内存。
您的C#互操作代码已损坏,并且在某些情况下似乎可以使用。 您不能希望以此方式进行。
互操作字符串的最简单方法是使用为此目的而设计的COM字符串BSTR
。 在C#端,将其作为带有MarshalAs(UnmanagedType.BStr)
属性的string
传递。 在Delphi端使用WideString
。
现在,使用BSTR
可以轻松地将字符串从非托管被叫方传递给托管呼叫者。 从另一个方向来看,这个问题不会出现。 您可以使用由调用方分配的以空终止的字符串。 在C#端以string
传递,并以PAnsiChar
或PWideChar
接收,具体取决于您如何对字符串进行编组。 同样,您可能更喜欢对所有字符串使用单一类型。 在这种情况下,请使用BSTR
。
一句话警告。 进行互操作时不要将WideString
用作函数返回类型: 为什么不能将WideString用作互操作的函数返回值?
一些例子:
德尔福
library Project1;
procedure Foo(InputVal: PWideChar; out OutputVal: WideString); stdcall;
begin
OutputVal := 'Foo: ' + InputVal;
end;
procedure Bar(InputVal: WideString; out OutputVal: WideString); stdcall;
begin
OutputVal := 'Bar: ' + InputVal;
end;
exports
Foo, Bar;
begin
end.
C#
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const string dllname = @"Project1.dll";
[DllImport(dllname, CharSet = CharSet.Unicode)]
static extern void Foo(
string InputVal,
[MarshalAs(UnmanagedType.BStr)]
out string OutputVal
);
[DllImport(dllname)]
static extern void Bar(
[MarshalAs(UnmanagedType.BStr)]
string InputVal,
[MarshalAs(UnmanagedType.BStr)]
out string OutputVal
);
static void Main(string[] args)
{
string OutputVal;
Foo("Hello", out OutputVal);
Console.WriteLine(OutputVal);
Bar("World", out OutputVal);
Console.WriteLine(OutputVal);
}
}
}
产量
Foo: Hello Bar: World
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.