我试图在我的InnoSetup项目中引用一个C#DLL。我需要的是一个带有一个字符串参数和一个字符串返回值的简单函数。但即使按照这个例子并尝试不同类型的编组,我总是会遇到访问冲突。
这是我的 C#类:
public class NKToolbox
{
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
{
File.WriteAllText(@"C:\temp\test.txt", password);
return password.Length.ToString();
}
}
我放置File.WriteAllText
以查看该方法是否被调用。但不是。我使用Robert Giesecke的UnmanagedExports包。
Inno设置代码:
function EncryptPassword(pw: WideString): WideString;
external 'EncryptPassword@files:nktoolbox.dll stdcall';
function InitializeSetup: Boolean;
var
str: WideString;
begin
str := EncryptPassword('sdvadfva');
log(str);
result := False;
end;
在str := EncryptPassword('sdvadfva')
行上,我在地址遭到访问违规行为......写下地址.....'我正在使用Inno Setup 5.5.9 Unicode。
我已尝试使用其他线程中发现的不同编组语句,我已尝试使用out
关键字,使用普通string
类型和{ {1}}无望。
答案 0 :(得分:2)
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
在Delphi代码中,这映射到:
function EncryptPassword(password: PAnsiChar): PAnsiChar; stdcall;
另请注意,C#代码返回通过调用CoTaskMemAlloc
分配的字符串。您的代码需要通过调用CoTaskMemFree
来解除分配该缓冲区。
导入此函数的代码会尝试将文本视为COM BSTR
字符串。事实并非如此。
使用COM BSTR
,又称WideString
是一个好主意。但要注意的是,C#和Inno之间可能存在不匹配,假定ABI为返回值。最好使用out
参数。见Why can a WideString not be used as a function return value for interop?
在你的鞋子里我会像这样声明C#:
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static void EncryptPassword(
[MarshalAs(UnmanagedType.BStr)]
string input
[MarshalAs(UnmanagedType.BStr)]
out string output
)
{
output = ...;
}
Inno就是这样:
procedure EncryptPassword(input: WideString; out output: WideString);
external 'EncryptPassword@files:nktoolbox.dll stdcall';
我对Inno一无所知,所以我的部分答案在某种程度上依赖于猜测。