FreePascal 64位DLL和调用C#应用程序
我正试图编译一个64位dll,用于64位C#应用程序。我有一个简单的类和一个简单的应用程序来尝试和测试它,无论我尝试和做什么,它都会失败。代码如下: 德尔菲FreePascal 64位DLL和调用C#应用程序,c#,delphi,freepascal,lazarus,C#,Delphi,Freepascal,Lazarus,我正试图编译一个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# 任何人
library project1;
{$mode objfpc}{$H+}
uses
Classes;
function Encrypt(aName:PChar):PChar;stdcall;
begin
Result := aName;
end;
exports Encrypt;
begin
end.
C#
任何人都能看到它有什么问题吗?如果不想创建相同的简单场景来尝试让它工作,我已经筋疲力尽了 问题在于,C#marshaller将一个临时内存块作为
aName
传递到函数中。当函数返回时,此内存将被销毁。但您也要求C#marshaller将相同的内存块编组为C#字符串
无论如何,从本机DLL函数返回以null结尾的字符串不是一个好的做法。您有两个选择:
StringBuilder
为字符串预分配内存。这需要您以某种方式获得所需的大小。这是互操作字符串的最常用方法BSTR
的形式返回字符串,C#marshaller知道如何对BSTR
进行封送和处置,并且有权访问COM分配器。我不知道如何在FreePascal中使用BSTR
,但在Delphi中,您只需使用WideString
。您还需要告诉C#marshaller您正在返回一个BSTR
procedure Encrypt(Input: WideString; out Output: WideString); stdcall;
begin
Output := Input;
end;
C#
@Jon这就是你在Delphi中所做的(
BSTR
==WideString
),但我不知道它在FP中是否也适用。如果在FP中不能这样做,那么调用SysAllocString
可能很容易,但需要获取UTF-16文本。看看这个答案:我刚刚将PChar改为Widestring并构建了DLL,但是C应用程序仍然不喜欢它。在C端,您需要使用marshallas(UnmanagedType.BStr)
,看几篇博客文章似乎表明WideString在FP中得到了很好的支持。看看JVCL和JclDotNet单元。
procedure Encrypt(Input: WideString; out Output: WideString); stdcall;
begin
Output := Input;
end;
[DllImport("project1.dll")]
public static extern void Encrypt(
[MarshalAs(UnmanagedType.BStr)] string input;
[MarshalAs(UnmanagedType.BStr)] out string output
);