c# - 我应该如何从 C# 调用这个 native dll 函数?

标签 c# .net delphi pinvoke delphi-7

这是 native (Delphi 7) 函数:

function Foo(const PAnsiChar input) : PAnsiChar; stdcall; export;
var
  s : string;
begin
    s := SomeInternalMethod(input);
    Result := PAnsiChar(s);
end;

我需要从 C# 调用它,但 dll 的名称在编译时未知 - 所以我必须使用 LoadLibrary 来获取它。

到目前为止,这是我的 C# 代码的样子:

[DllImport("kernel32.dll")]
public extern static IntPtr LoadLibrary(String lpFileName);

[DllImport("kernel32.dll")]
public extern static IntPtr GetProcAddress(IntPtr handle, string funcName);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate string FooFunction(string input);

...

IntPtr dllHandle = LoadLibrary(dllName);
IntPtr fooProcAddr = GetProcAddress(dllHandle, "Foo");

FooFunction foo = (FooFunction)Marshal.GetDelegateForFunctionPointer(
    fooProcAddr, typeof(FooFuncion)
);

string output = foo(myInputString);

现在,这实际上起作用了——至少,delphi 代码正确地接收到字符串,而 C# 代码接收到输出字符串。

但是,当调试从 C# 代码调用的 delphi 代码时,我注意到一些奇怪的地方——调试器在不应该跳过的行时跳过了一些行。

我担心我正在泄漏内存 - 有人清理了那些 PChars 吗?

谁能给我一些关于如何完成的反馈/建议?

最佳答案

你能做的唯一合理的事情就是丢弃这个函数并重写它。这是永远行不通的。 sFoo() 函数的局部字符串变量,所以当您离开Foo() 时,该字符串占用的内存将被释放。您返回的指针指向无效的内存位置,该位置偶然仍包含字符串数据。如果您使用内存管理器在释放指向它的指针时清除内存,它甚至不会再包含数据。如果内存被重用,它将包含其他内容,如果包含该内存块的 block 被释放,您将获得一个 AV。

这里有更多关于 StackOverflow 如何从 DLL 返回字符序列数据的问题。要么使用与 Windows API 处理业务的方式兼容的字符串类型,COM 字符串,要么将预分配的缓冲区传递给您的函数并用数据填充它。在后一种情况下,您可以使用与每个类似 API 函数相同的方式来使用您的函数。

关于c# - 我应该如何从 C# 调用这个 native dll 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1704762/

相关文章:

arrays - Delphi - TStack 容量困惑

c# - 从 ArrayList 获取变量的好方法包括不同类型的列表吗?

c# - ASP MVC 重定向而不改变 URL(路由)

C# 视频播放器

delphi - 下载前使用 WinInet 确定文件总大小

delphi - 在关闭并重新打开应用程序之前,日期格式无法正确显示

c# - 在 ASP.NET 和 XDocument.Load 中获取文件路径

c# - 异步访问的数据接口(interface)

c# - 避免冗余的异步计算

c# - System.Speech.Recognition 备选匹配项和置信度值