Могу ли я использовать заголовки C в Delphi? - PullRequest
2 голосов
/ 06 января 2011

Можно ли скомпилировать заголовки C с помощью компилятора Rad Studio XE C ++ и связать их с кодом Delphi?

Таким образом устраняется необходимость конвертировать заголовочные файлы в паскаль?

Причиной вопроса является ..

C - Определение заголовка:

DLLEXPORT int url_engine_version(char *version, size_t length);

Попытка определения Delphi

function url_engine_version(version: PByte; var length: cardinal): integer;
  cdecl; external 'corplib.dll';

Главное приложение пыталось вызвать его, используя:

engVer: Pointer;
engLen: cardinal;

engLen := 64;
GetMem(engVer,engLen);
url_engine_version(engVer,engLen);

Но Delphi AV пытается вызвать рутину.

Рабочее определение C # - Чик работает, если я передаю StringBuilder с предопределенной длиной 64

[DllImport("corplib.dll", CharSet = CharSet.Ansi,
           CallingConvention = CallingConvention.Cdecl)]
public static extern int url_engine_version(StringBuilder version, [Out] int length);

Ответы [ 3 ]

3 голосов
/ 06 января 2011

Ответ на ваш актуальный вопрос: Нет. Извините.

Однако я думаю, что в этом случае проблема довольно проста ...

Либо заголовок C, который вы воспроизвели здесьневерно, или объявление C #, или вам просто очень повезло, что код C # не аварийно завершает работу и работает так же плохо, как код Delphi.

Проблема, которую я считаю, заключается в том, что заголовок C объявляет длина параметр в качестве SIZE_T, NOT указатель на SIZE_T.то есть это входной параметр, а не выходной или входной / выходной.

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

Версия Delphi завершается сбоем, я полагаю, потому чтоуказав length как var , вы передаете length по ссылке, т.е. функция получает не «64», а указатель на значение «64», ноиспользует это значение указателя, а не значение 64.

Код C # может уклоняться от маркера (также неверно, если сам заголовок C верен), объявляя параметр как out .Это может привести к чему-то, что, если не правильно, по крайней мере, не так «ужасно некорректно» во время выполнения.

Я думаю, что простое удаление «var» из объявления параметра длины должно решить вашу проблему:

function url_engine_version(aVersion: PByte; aLength: cardinal): integer; cdecl; external 'corplib.dll';
1 голос
/ 06 января 2011

Основная проблема с конвертацией - это различия в системе типов.Хороший заголовок delphi не может быть получен из c.

Например, c не различает указатели на один элемент и указатели на массивы.Это не различает bools и ints.char* может означать строку с нулем в конце, указатель на байты, указатель на один символ, символ, переданный по ссылке, ...

И в вашем примере код delphi передает последний параметр какссылка (т.е. как указатель на UInt32), а код c - нет.Но я не понимаю, почему код C # работает.

0 голосов
/ 06 января 2011

Проект JEDI сделал много преобразований C-заголовков для Delphi.У них есть отличный набор ресурсов, учебных пособий и т. Д. На их веб-сайте .

У них также есть инструмент, который может автоматизировать этот процесс, который был фактически получен из оригинального кода Боба Сварта.

...