7

我正在尝试编译一个 64 位 dll 以用于 64 位 C# 应用程序。我有一个简单的类和一个简单的应用程序来尝试和测试它,无论我尝试做什么,它都会失败。这是代码:

德尔福

library project1;

{$mode objfpc}{$H+}

uses
  Classes;


function Encrypt(aName:PChar):PChar;stdcall;
begin
  Result := aName;
end;


exports Encrypt;

begin
end.

C#

 [DllImport("project1.dll")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern String Encrypt([MarshalAs(UnmanagedType.LPStr)] String aName);

任何人都可以看出它有什么问题吗?如果不喜欢创建相同的简单场景来尝试让它发挥作用,我就完蛋了!

4

1 回答 1

11

The problem with this is that the C# marshaller passes a temporary block of memory into the function as aName. This memory is the destroyed when the function returns. But you are also asking the C# marshaller to marshal this same block of memory into a C# string.

It's not good practice to return a null-terminated string from a native DLL function anyway. You have a couple of options:

  1. Use a StringBuilder on the C# side to pre-allocate the memory for the string. This requires you to get hold of the required size somehow. This is the most common way to interop strings.
  2. Return the string as a COM BSTR and the C# marshaller knows how to marshall and dispose a BSTR, and has access to the COM allocator to do so. I have no knowledge about using BSTR in FreePascal but in Delphi you simply use WideString. You also need to tell the C# marshaller that you are returning a BSTR.

I personally have a preference for option 2. There is one wrinkle though and that is that different compilers use a different ABI for function return values, as discussed at this question: Why can a WideString not be used as a function return value for interop? The easy way around that is to return the string in a parameter rather than using the function return value.

The code looks like this:

Pascal

procedure Encrypt(Input: WideString; out Output: WideString); stdcall;
begin
  Output := Input;
end;

C#

[DllImport("project1.dll")]
public static extern void Encrypt(
    [MarshalAs(UnmanagedType.BStr)] string input;
    [MarshalAs(UnmanagedType.BStr)] out string output
);
于 2011-06-13T19:31:52.807 回答