2014-12-07 1 views
0

Как я могу получить строку из FPC DLL? Я хотел бы отправить два указателя, конкатенировать их и получить результат в другой строке в Delphi.Как я могу получить строку из FPC DLL?

library Test; 

{$mode Delphi} 

uses 
    Classes; 

function Concat(const S1, S2: PWideChar): String; cdecl; 
begin 
    Result := S1 + S2; 
end; 

exports 
    Concat name 'Concat'; 

begin 
end. 
+0

Обычно вызывающий абонент выделяет память, и вызывающий ее заполняет –

+0

@DavidHeffernan Как именно? –

+0

Ну, вызывающий абонент выделяет память и передает указатель на эту память. Вызвав его. –

ответ

3

В Delphi, строка представляет собой сложный, структурированный тип с большим количеством деталей, управляемыми для вас компилятора и RTL «магией», который скрывает эти детали. В частности, для «длинных строк» ​​есть счетчик ссылок и длина и, в зависимости от используемой версии Delphi, возможно, другая информация.

Любая DLL не может точно знать, какая информация требуется для возврата (или может присутствовать) любых «строковых» переменных (или результатов), которые могут потребоваться приложению. DLL вообще не может быть вызвана программой Delphi, и в этом случае тип «string» будет совсем другим.

По этой причине DLL обычно будет иметь дело со строками как простой «C'-стиль» указатель на char. То есть, некоторый указатель на область с нулевым завершением памяти. Затем вызывающий вызывающий DLL должен также обеспечить обмен значениями «string» с DLL соответственно.

В случае некоторой функции, возвращающей значение, проблема осложняется тем фактом, что выделение области памяти, требуемой для хранения результата, должно выполняться вызывающим абонентом, при этом функция в DLL принимает соответствующие меры убедитесь, что достаточная память. Применение этих принципов в данном случае приводит к DLL подпрограммы, которая может выглядеть примерно так:

function Concat(const S1, S2, DEST: PWideChar; const aMaxLen: Integer): Boolean; cdecl; 
begin 
    // left as exercise 
end; 

Это простая реализация, которая возвращает TRUE, если aMaxLen достаточно для размещения сцепленного результата. Вы должны также рассмотреть другое поведение функции при различных условиях (например, S1. или S2 или как являются NIL, aMaxLen является слишком большим и т.д.).

Независимо от вариантов реализации сделаны для выполнения конкатенации (слева как упражнение для вас), то результат вызова функции должен быть поместить результат в буфер указал на по DEST.

Вызывающий должен затем также гарантировать, что буфер достаточной длины обеспечивается и правильной длины, указанный в вызове:

var 
    a, b, ab: WideString; // Or: String or UnicodeString in Delphi 2009 and later 
begin 
    a := 'foo'; 
    b := 'bar'; 

    // Make sure 'ab' is big enough to hold the concatenated result of a + b 
    SetLength(ab, Length(a) + Length(b)); 

    if Concat(PWideChar(a), PWideChar(b), PWideChar(ab), Length(ab)) then 
    // success: ab == 'foobar' 
    else 
    // something went wrong 
end; 

Этот вопрос нужно задать, хотя: Почему вы это делаете в FPC DLL, когда Delphi уже справляется с конкатенацией строк довольно комфортно? O.o

+0

Я боюсь, что использование 'WideString' приведет к ужасной производительности. Почему бы не придерживаться регулярного 'UnicodeString'? –

+0

Вы хотите, чтобы это сработало? –

+0

@DavidHeffernan Я хочу, чтобы он работал и работал быстро. 'WideString' и его C++-аналог' BSTR' являются чем-то вроде 1000x медленнее, чем Delphi 'String'. Существует решение [здесь] (http://stackoverflow.com/questions/7925023/need-simple-demo-call-delphi-dll-in-c) благодаря Реми. –