【问题标题】:Why does calling libsass functions with .NET P/Invoke fail?为什么使用 .NET P/Invoke 调用 libsass 函数会失败?
【发布时间】:2016-09-25 16:28:32
【问题描述】:

我已经使用the included solution fileslibsass 3.3.6 编译成一个带有VS 2015 的DLL。运行下面的代码会导致程序立即崩溃而没有输出。

using System;
using System.Runtime.InteropServices;

namespace Sass.Cli {
static class Sass {
    [DllImport(@"C:\...\libsass\win\bin\libsass.dll")]
        public static extern String libsass_version();
    }
    class Program {
        static void Main(string[] args) {
            Console.WriteLine(Sass.libsass_version());
        }
    }
}

调用函数的来源是sass.cpp:61

const char* ADDCALL libsass_version(void)

DLL 和上述代码都是针对 x86 编译的。在崩溃时运行 VS 调试器会出现以下异常:Sass.Cli.exe 中 0x771A9841 (ntdll.dll) 处的未处理异常:0xC0000374:堆已损坏(参数:0x771DC8D0)。 p>

这是可以修复的还是我忽略的?还是只是 libsass DLL 当前无法工作?

【问题讨论】:

    标签: c# .net pinvoke dllimport libsass


    【解决方案1】:

    string 用作返回类型时,框架假定它是通过调用CoTaskMemAlloc 分配的。然后它通过调用CoTaskMemFree 复制字符串的内容和释放。这就是你的错误的解释。

    通过将返回值更改为IntPtr并以Marshal.PtrToStringAnsi获取字符串内容来解决。您无需处理任何已定位的内容,因为此版本字符串将是静态的。

    我不知道调用约定是什么。您应该检查代码和文档以找出答案。尽管如此,这个函数非常简单,以至于它对 cdecl 和 stdcall 的行为方式相同,因此无法解释错误。尽管如此,您仍需要为图书馆的其余部分做好准备。

    请注意,我在这里有点猜测。你没有提供完整的细节。您应该查阅代码和文档以仔细检查我的猜测。

    【讨论】:

    • 这确实解决了它,尽管它输出的版本是 [NA]。不过,我猜这完全不相关,所以我将其标记为已回答。
    • 另外,在未来,还有哪些细节可以帮助澄清这一点?我确定我会再次遇到 P/Invoke 问题。
    • 你没有告诉我们什么是ADDCALL,你也没有解释如何释放返回值的内存,或者不。
    • 我的错,那是因为我根本不知道它是如何工作的。不过,既然我这样做了,我会牢记这一点。
    猜你喜欢
    • 2014-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    相关资源
    最近更新 更多