2016-08-23 8 views
0

Я пытаюсь ссылаться на C# DLL в моем проекте InnoSetup. Мне нужна простая функция с одним строковым параметром и возвращаемым значением строки. Но даже после примера и попыток разного рода маршалинга я всегда оказываюсь в нарушении доступа.C# DLL в Inno Setup Access Violation

Это мой 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, чтобы увидеть, если метод даже называется. Но нет. Я пользуюсь пакетом UnmanagedExports от Роберта Гизеке.

И Inno Setup Code:

function EncryptPassword(pw: WideString): WideString; 
external '[email protected]: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 и WideString безнадежно.

ответ

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, aka 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 '[email protected]:nktoolbox.dll stdcall'; 

Я ничего не знаю о Inno, так что часть моего ответа несколько зависит от догадок.

+0

Извините за поздний ответ, у меня не было времени проверить его до сих пор. Однако это работает как шарм! Спасибо. –