Search code examples
c#.netpinvokedllimportlibsass

Why does calling libsass functions with .NET P/Invoke fail?


I’ve compiled libsass 3.3.6 into a DLL with VS 2015 using the included solution files. Running the code below causes the program to crash immediately with no output.

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());
        }
    }
}

The source for the invoked function is at sass.cpp:61.

const char* ADDCALL libsass_version(void)

Both the DLL and the above code were compiled for x86. Running the VS debugger on crash gives me the following exception: Unhandled exception at 0x771A9841 (ntdll.dll) in Sass.Cli.exe: 0xC0000374: A heap has been corrupted (parameters: 0x771DC8D0).

Is this something that can be fixed or that I’ve overlooked? Or is it just the case that libsass DLLs aren’t currently working?


Solution

  • When a string is used as a return type then the framework assumes it was allocated by calling CoTaskMemAlloc. It then copies the content of the string and deallocation by calling CoTaskMemFree. That is the explanation for your error.

    Solve it by changing the return value to IntPtr and getting the string content with Marshal.PtrToStringAnsi. You won't need to deal located anything since this version string will be static.

    I can't tell what the calling convention is. You should check the code and docs to find out. Still, this function is so simple that it behaves the same way for both cdecl and stdcall so that can't explain the error. Still, you will need to get it right for the rest of the library.

    Note that I am guessing a little here. You've not provided full details. You should consult the code and docs to double check my guesswork.