[英]“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.