Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Проблема с загрузкой символов в динамической библиотеке Free Pascal на macOS и её решение

Delphi , Синтаксис , Ошибки и Исключения

 

При разработке динамических библиотек (dylib) на Free Pascal для macOS, можно столкнуться с неожиданной проблемой: библиотека успешно загружается, но dlsym не находит экспортируемые символы, хотя они видны в таблице символов (например, через nm). Эта проблема не возникает на Windows, что делает ее особенно коварной. В этой статье мы рассмотрим причины этой проблемы и предложим решение, а также альтернативный подход.

Суть проблемы:

Проблема возникает из-за использования конструкции name в секции exports файла проекта Free Pascal. Например:

exports
  GetName name 'GetName',
  GetBid name 'GetBid',
  GetCard name 'GetCard';

На macOS, Free Pascal при использовании name создает символы, которые появляются в статической таблице символов (видимой для nm), но не добавляются корректно в динамическую таблицу символов, необходимую для dlsym. Это приводит к тому, что библиотека загружается, nm показывает экспортированные символы, но dlsym возвращает NULL и сообщает об ошибке "symbol not found".

Решение:

Самое простое и эффективное решение – полностью удалить конструкции name из секции exports, если имя экспортируемой функции совпадает с именем функции в коде.

exports
  GetName,
  GetBid,
  GetCard;

Почему это работает:

  • Функции экспортируются под своими исходными именами.
  • Символы корректно добавляются как в статическую, так и в динамическую таблицу символов.
  • dlsym успешно находит символы.
  • Решение работает как на Windows, так и на macOS.

Пример кода на C (для проверки):

#include <stdio.h>
#include <dlfcn.h>

int main() {
  void* handle = dlopen("./libplayer.dylib", RTLD_LAZY);
  if (!handle) {
    fprintf(stderr, "Error: %s\n", dlerror());
    return 1;
  }

  void* symbol = dlsym(handle, "GetName");
  if (!symbol) {
    fprintf(stderr, "Error: %s\n", dlerror());
    dlclose(handle);
    return 1;
  }

  printf("Symbol 'GetName' found!\n");

  dlclose(handle);
  return 0;
}

Ключевой вывод: Использование name необходимо только тогда, когда вы хотите изменить имя экспортируемого символа. Если имя экспортируемой функции совпадает с именем функции в коде, отказ от name позволяет избежать этой специфичной для macOS проблемы линковки.

Альтернативное решение (использование директивы {$EXTERNAL}):

Если вам действительно необходимо изменить имя экспортируемой функции (например, для совместимости с существующим API на C), можно использовать директиву {$EXTERNAL}. Этот подход требует немного больше кода, но позволяет сохранить контроль над именами экспортируемых символов.

library player;

{$mode delphi}

uses
  SysUtils;

function GetNameFunc: PChar; cdecl;
begin
  Result := 'Player Name';
end;

exports
  GetNameFunc name 'GetName';

begin
end.

Затем, в вашем C коде, вы будете использовать имя 'GetName':

#include <stdio.h>
#include <dlfcn.h>

typedef char* (*GetNameType)();

int main() {
  void* handle = dlopen("./libplayer.dylib", RTLD_LAZY);
  if (!handle) {
    fprintf(stderr, "Error: %s\n", dlerror());
    return 1;
  }

  GetNameType GetName = (GetNameType)dlsym(handle, "GetName");
  if (!GetName) {
    fprintf(stderr, "Error: %s\n", dlerror());
    dlclose(handle);
    return 1;
  }

  printf("Player Name: %s\n", GetName());

  dlclose(handle);
  return 0;
}

Важно: При использовании {$EXTERNAL} убедитесь, что соглашения о вызовах (calling conventions) совпадают между Pascal и C (в данном примере cdecl).

Заключение:

Проблема с dlsym на macOS при использовании динамических библиотек Free Pascal, как правило, связана с некорректным использованием конструкции name в секции exports. Простое удаление этой конструкции, если имена совпадают, решает проблему в большинстве случаев. Если необходимо изменить имя экспортируемой функции, используйте директиву {$EXTERNAL}, тщательно следя за соглашениями о вызовах. Понимание этих нюансов позволит вам создавать кроссплатформенные динамические библиотеки на Free Pascal без лишних проблем.

Создано по материалам из источника по ссылке.

В статье рассматривается проблема загрузки символов в динамической библиотеке Free Pascal на macOS, вызванная использованием конструкции `name` в секции `exports`, и предлагается решение путем ее удаления или использования директивы `{$EXTERNAL}`.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Ошибки и Исключения ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-09-03 05:35:56/0.0035941600799561/0