2013-04-19 6 views
2

У меня проблемы с имён DLL с Delphi. Функция Delphi DLL объявляется как здесь:Передача PChar из Delphi DLL в C

function TEST() : PChar; cdecl; 
begin 
    Result := '321 Test 123'; 
end; 

В C++ я называю это так:

typedef char *TestFunc(void); 
TestFunc* Function; 
HINSTANCE hInstLibrary = LoadLibrary("Test.dll"); 
if (hInstLibrary) 
{ 
    Function = (TestFunc*)GetProcAddress(hInstLibrary, "TEST"); 
    if (Function) 
    { 
     printf("%s", Function()); 
    } 
} 

Проблема заключается в том, что я только получать первую букву строки. Как я могу сказать C++, что строка не заканчивается после первого символа?

Благодаря

+0

Какая версия delphi? Вам нужно знать, имеет ли символ 1 или 2 байта. –

+0

Или попробуйте использовать PAnsiChar. –

+0

Я использую Delphi Xe2 – Henry

ответ

2

У вас есть две проблемы:

  1. Строка, Delphi посылает к вам UTF-16 в кодировке. Вам нужно будет закодировать как ANSI и вернуть PAnsiChar, если вы хотите совпадение с char*.
  2. Память, на которую ссылается возвращенный указатель, может быть освобождена при возврате функции. Вы избегаете его в своей функции, так как вы возвращаете строковый литерал, который хранится как глобальная константа, которая выдерживает время жизни библиотеки DLL. Для строковой переменной вы столкнетесь с ошибками во время выполнения, когда ваш вызывающий объект пытается прочитать память, которая была освобождена. Чтобы запутать вопросы, эти ошибки времени выполнения будут прерывистыми. Возможно, ваш код работает. Ожидайте сбоев при развертывании вашего самого важного клиента!

Ваши варианты решения Пункт 2:

  1. Arrange, что вызывающий выделяет буфер, который затем может быть заселен вызываемым.
  2. Выделить и освободить строку на общей куче. Например, куча COM с CoTaskMemAlloc и CoTaskMemFree. Использование общей кучи позволяет выделять в одном модуле и освобождать в другом.

Как правило, всегда предпочитайте вариант 1, если он может удовлетворить ваши потребности.

+0

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

+1

Вас не интересует «значение указателя». Вас интересует память, на которую она ссылается. И если эта память будет освобождена, когда функция вернется, ваш код C будет иметь недопустимый указатель. Чтение из этой памяти - это неопределенное поведение. Поэтому, если у вас была строка Delphi под названием 'mystr', и вы написали' 'Result: = PAnsiChar (mystr)' в своей DLL-функции, у вас возникнут проблемы. Память, на которую ссылается «Результат», будет освобождена при возврате функции. –

+1

Вариант 3: выделить в dll (например, GetMem) и подпрограмму экспорта из библиотеки DLL – Remko

Смежные вопросы