原生DLL - C#

时间:2016-11-05 16:50:29

标签: c# delphi dll

我在Delphi中编写了本机DLL库。我想从C#引用这个lib并获得返回的字符串。

功能

// Example, in your case you have this after the for loop
var artistCounts = {};

artistCounts["beyonce"] = 135;
artistCounts["rihanna"] = 67;
artistCounts["taylor swift"] = 45;
artistCounts["drake"] = 199;


// Create array of objects
var t = [];
for (var k in artistCounts) {
    if (artistCounts.hasOwnProperty(k)) {
        t.push({"name": k, "count": artistCounts[k]});
    }
}

// Sort by count, descending
t.sort(function(a, b) {
   return a.count < b.count
});

t.slice(0, 5); // Your top 5

C#代码

function GetCode (aUser,aPassword: PAnsiChar): PAnsiChar; stdcall;

尝试调用函数应用程序退出,代码为-1073740940(0xc0000374)。

你有任何过期吗?谢谢你的帮助

1 个答案:

答案 0 :(得分:4)

返回值为string时,编组人员负责释放返回的字符串。它通过调用CoTaskMemFree来实现。毫无疑问,您的字符串未在COM堆上分配。因此,错误是NTSTATUS错误代码STATUS_HEAP_CORRUPTION

您的p / invoke应该返回IntPtr而不是这样:

[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
private static extern IntPtr GetCode(string aUser, string aPassword);

要获取字符串,请将返回值传递给Marshal.PtrToStringAnsi

public string getCode(string login, string password) 
{
    IntPtr retval = GetCode(login, password);
    string result = Marshal.PtrToStringAnsi(retval);
    // how do we deallocate retval
    return result;
}

另请注意,我删除了多余的MarshalAs属性。 CharSet.Ansi负责输入参数编组。

您仍然需要弄清楚如何释放返回的内存。我们无法分辨它是如何分配的。您需要联系Delphi代码的开发人员,或阅读源代码。如果使用本机Delphi堆,请不要感到惊讶,这会使您处于绑定状态。通过调用CoTaskMemAlloc来使用COM堆实际上并不是一个糟糕的选择,然后你的原始p / invoke返回值string就可以了。

其他选项包括导出解除分配器或要求调用者分配缓冲区。网上有很多关于如何实现各种选项的例子。