Вызов двух функций с одинаковым именем из двух разных библиотек C - PullRequest
8 голосов
/ 13 ноября 2008

У меня есть две C библиотеки DLL, к которым мне нужен доступ в одном исполняемом файле. У меня есть заголовочные файлы и файлы .LIB для обеих библиотек. К сожалению, подмножество функций, к которым мне нужно получить доступ, имеют точно такие же имена. Лучшее решение, которое мне удалось найти, - это использовать LoadLibrary для загрузки одной из библиотек DLL и явного вызова ее методов с помощью GetProcAddress. Есть ли способ для меня неявно загрузить обе библиотеки и как-то дать подсказку компилятору, что в одном случае я хочу вызвать OpenApi в DLL A, а в другом случае я хочу вызвать OpenApi в DLL B?

Я разрабатываю свой исполняемый файл на C ++ с использованием Visual Studio 2008 и соответствующей библиотеки времени выполнения C (msvcr90.dll).

[Изменить]

Комментатор Илья спрашивает ниже, что мне не нравится в решении GetProcAddress. Мне это не нравится по двум причинам:

  1. Это делает код более сложным. Одна строка кода для вызова функции заменяется тремя строками кода, одна для определения сигнатуры функции, одна для вызова GetProcAddress и одна для фактического вызова функции.
  2. Это более подвержено ошибкам во время выполнения. Если я неправильно напишу имя функции или испорчу подпись, я не увижу ошибку до времени выполнения. Скажем, я решил интегрировать новую версию библиотеки DLL, и одно из имен методов изменилось, оно будет прекрасно компилироваться и не будет иметь проблем до фактического вызова GetProcAddress, который может быть даже пропущен при прохождении теста.

Ответы [ 3 ]

4 голосов
/ 13 ноября 2008

Раньше вы могли «переименовывать» импортированный символ, используя файл компоновщика .def. Вы, вероятно, все еще можете, но прошло много времени с тех пор, как широко использовались файлы .def, и найти документацию сложно.

В текущей документации MSDN директива IMPORTS указана как «зарезервированное ключевое слово». Я не уверен, означает ли это, что они удалили функциональность или просто не хотят больше ее поддерживать.

Вот на странице, которая описывает директиву ИМПОРТ:

http://www.digitalmars.com/ctg/ctgDefFiles.html#imports

Другие хитрые альтернативы:

  1. создание функций-оболочек для конфликтующих API. Эти функции могут танцевать LoadLibrary()/GetProcAddress(). Все другие не конфликтующие функции могут быть неявно связаны как обычно. На самом деле, это решение, вероятно, наименее сложное из 3 в этом ответе.

  2. создать 2 библиотеки DLL-оболочки, чтобы каждая из них ссылалась только на одну или другую библиотеку с конфликтующими именами. Используйте разные имена в библиотеках-оболочках, которые просто передаются реальным библиотекам. Обратите внимание, что библиотекам-оболочкам не нужно оборачивать все API-интерфейсы - им просто нужно обернуть конфликтующие.

1 голос
/ 13 ноября 2008

Мне удалось прийти к хитрой альтернативе Майка Б. № 2 (или № 3, если учесть исходное предложение) после того, как я немного подумал над этим вопросом.

Это мой любимый из трех для моего конкретного случая , потому что, кажется, он требует наименьшего объема работы и, вероятно, может быть наиболее очевидным для расшифровки кому-то новому, глядя на код. Я считаю, что могу просто выполнить следующие шаги и начать работу:

  1. используйте магию регулярных выражений и найдите / замените, чтобы превратить файлы заголовков с вызовами функций, которые у меня есть, в файл заголовка оболочки и файл реализации оболочки. (где каждый метод в dll-оболочке отличается каким-то общим новым элементом для имени, что экономит мне время на необходимость разрешения конфликтов). Таким образом, FunctionCall () становится WrapperOneFunctionCall () и WrapperTwoFunctionCall () в каждой соответствующей dll-оболочке.
  2. связывает dll-оболочку с соответствующей базовой dll.
  3. связывает мой исполняемый файл с dll-оболочкой, удаляет ссылки на базовые dll, но по-прежнему включает определения констант, enum и struct, которые не нужно разрешать из базовой dll (поскольку мои функции-оболочки по-прежнему принимают один и тот же параметр типы)

Если кто-то еще читает эту ветку, мой следующий вопрос будет: «Что-то не так с этим решением?»

Спасибо респондентам за помощь.

1 голос
/ 13 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...