2013-12-25 13 views
2

У меня есть DLL C#, которая предоставляет функцию с использованием Unmanaged Exports, которая вызывается непосредственно скриптом Inno Setup Pascal. Эта функция должна вернуть строку в Inno Setup. Мой вопрос: как я могу это сделать?
Мой предпочтительный метод - передать буфер от Inno Setup функции C#, которая вернет строку внутри этого буфера. Я пришел с этим кодом:Возвращение строки из C# DLL с неуправляемым экспортом в скрипт установки Inno

C# функции:

[DllExport("Test", CallingConvention = CallingConvention.StdCall)] 
static int Test([Out, MarshalAs(UnmanagedType.LPWStr)] out string strout) 
{ 
    strout = "teststr"; 
    return strout.Length; 
} 

Inno скрипт установки:

function Test(var res: String):Integer; external '[email protected]:testdll.dll stdcall'; 

procedure test1; 
var 
    Res: String; 
    l: Integer; 
begin 
    SetLength(Res,256); 
    l := Test(Res); 
    { Uncommenting the following line causes an exception } 
    { SetLength(Res,l); } 
    Log('"Res"'); 
end; 

Когда я запускаю этот код переменной Res пуст (я вижу "" в log)

Как я могу вернуть строку из этой DLL?

Обратите внимание, что я использую версию Inno Setup для Unicode. Я также не хочу использовать COM для вызова этой функции или выделения буфера в DLL и вернуть его в Inno Setup.

+0

Почему в в мире кто-то проголосовал так? [+1] – TLama

+0

Они не документируют это. Лучше всего предположить, что StringBuilder без * out * и атрибута MarshalAs. Если вы получаете китайский, то используйте CharSet.Auto –

ответ

5

Я предлагаю вам использовать тип BSTR, который используется для типа данных для вызовов функций interop. На вашей стороне C# вы должны настроить свою строку как тип UnmanagedType.BStr, а на стороне установки Inno вы должны использовать WideString, который совместим с типом BSTR. Так что ваш код будет затем изменить это (смотрите также Marshalling sample главу из неуправляемых Exports документы):

[DllExport("Test", CallingConvention = CallingConvention.StdCall)] 
static int Test([MarshalAs(UnmanagedType.BStr)] out string strout) 
{ 
    strout = "teststr"; 
    return 0; // indicates success 
} 

И на стороне Inno Setup с использованием WideString к этому:

[Code] 
function Test(out strout: WideString): Integer; 
    external '[email protected]:testdll.dll stdcall'; 

procedure CallTest; 
var 
    retval: Integer; 
    str: WideString; 
begin 
    retval := Test(str); 
    { test retval for success } 
    Log(str); 
end; 
+0

Спасибо! Это решило проблему! – Ohad

+0

Добро пожаловать! – TLama

+1

Некоторые причуды здесь. Нет необходимости в атрибуте Out. Это подразумевается ключевым словом. И предварительное распределение ширины неверно. Это параметр out. Вызов будет выделен вызовом SysAllocString. Я бы с удовольствием отредактировал для вас. –