1

我如何在 C# 中使用这个 dll 函数?我尝试了以下但我得到错误。“外部组件引发的异常。”

我第一次用 C# 和 Delphi 做这个 PInvoke 的东西。

function HTTPGET(location:string):string; stdcall;
var
HTTP:TIdHttp;
begin
  HTTP := TidHttp.Create(nil);
  try
    result := HTTP.Get(location);
  finally
  FreeAndNil(HTTP);
  end;
end;


exports
  HTTPGET;

begin
end.


namespace Test
{
    class Program
    {
        [DllImport("project1.dll")]
        public static extern string HTTPGET(string location);

        static void Main(string[] args)
        {
           Console.WriteLine(HTTPGET("http://www.reuters.com/"));
        }
    }
}
4

4 回答 4

7

您不能从 C# 调用该函数。那是因为您不能使用 Delphistring进行互操作。您可以使用PAnsiChar从托管到非托管传递的字符串,但在另一个方向它更复杂。您需要在调用者处分配内存,或使用共享堆。我更喜欢使用 COM 最容易完成的后一种方法BSTR。这是WideString在德尔福。

如前所述您不能将WideString其用作互操作的返回值,因为 Delphi 使用与 MS 工具不同的 ABI 作为返回值。

Delphi 代码需要如下所示:

procedure HTTPGET(URL: PAnsiChar; out result: WideString); stdcall;

在 C# 方面,您可以这样编写:

[DllImport("project1.dll")] 
public static extern void HTTPGET(
    string URL,
    [MarshalAs(UnmanagedType.BStr)]
    out string result
);     

如果您希望 URL 使用 Unicode,请使用PWideCharCharSet.Unicode

procedure HTTPGET(URL: PWideChar; out result: WideString); stdcall;
....
[DllImport("project1.dll", CharSet=CharSet.Unicode)] 
public static extern void HTTPGET(
    string URL,
    [MarshalAs(UnmanagedType.BStr)]
    out string result
);     
于 2013-05-19T17:59:20.023 回答
0

不要使用string类型:字符串需要内存管理,而 C# 和 Delphi 模块显然使用不同的内存管理器(不管 C# 通过char*和 Delphi 期望String的)。尝试location在 DLL 中将类型更改为 PChar,并更改结果类型,使其为 PChar (应显式分配缓冲区)或其他内容,但不是string.

于 2013-05-19T17:42:57.343 回答
-1

尝试使用 Robert Giesecke 的 C# 非托管导出

https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

由于与 php 的兼容性,我们在 Delphi App 中使用来自 c# 的加密引擎并且运行良好(因此,不存在提到的字符串问题)。

我们之前的解决方案(更糟糕):将 c# dll 注册为 com 组件并使用它。上述解决方案输出库必须放在 exe 目录中,无需注册即可正常工作:)

于 2013-05-21T12:10:06.887 回答
-1

我记得,你不能用 C# 编组 delphi 字符串......你必须使用 PChar 的解决方法并自己管理内存,或者使用类似于此处最后一个答案中提供的解决方法:

在 C# 中使用 Delphi 的 stuct 数组和字符串

于 2013-05-19T17:48:45.557 回答