Зависимость DLL от статической библиотеки - PullRequest
0 голосов
/ 16 октября 2018

В настоящее время я создаю для наших клиентов чисто статическую библиотеку MainLib, которая содержит все символы, чтобы они могли интегрировать ее в свою программу.По нескольким причинам мне теперь нужно доставить версию DLL из MainLib, которая содержит части символов вместе со статической библиотекой FeatureLib, которая содержит оставшиеся символы.Одна из причин заключается в том, что мы хотим избежать использования нашего программного обеспечения плохими парнями, просто крадя библиотеку DLL, которая предоставляется программой нашего клиента.Это не будет работать, если части символов интегрированы в вызывающее программное обеспечение через статическую библиотеку .Пользователь пакета может использовать DLL только в том случае, если он добавил символы FeatureLib в свое приложение.

Для Linux я могу заставить эту работу работать как шарм, т. Е. Символ doFeature() находится за пределами libMainLib.so, но мне не удается это сделать для Windows.

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)

project(MainLib)

add_library(FeatureLib STATIC src/FeatureLib.c)
target_include_directories(FeatureLib PUBLIC include
                                      PRIVATE src)

add_library(MainLib SHARED src/MainLib.c)
target_include_directories(MainLib PUBLIC include
                                   PRIVATE src)

# I don't want to include symbols from FeatureLib into shared MainLib
#target_link_libraries(MainLib PRIVATE FeatureLib)

add_executable(MainLibDemo src/demo.c)
target_link_libraries(MainLibDemo MainLib FeatureLib) #resolve symbol doFeature()

FeatureLib.h:

extern int doFeature(int input);

MainLib.h:

extern __declspec(dllexport) int MainLib(int input);

FeatureLib.c:

#include "FeatureLib.h"
int doFeature(int input) {return 4;}

MainLib.c:

#include "FeatureLib.h"
#include "MainLib.h"

__declspec(dllexport) int MainLib(int input)
{
  if (input > 2) {
    return doFeature(input);
  } else {
    return doFeature(0);
  }
}

demo.c:

#include <stdio.h>
#include <stdlib.h>

#include "MainLib.h"

int main(int argc, char **argv)
{
  if(argc > 1)
    return MainLib(atoi(argv[1]));
  else
    return 0;
}

При этом я получаю следующую ошибку компиляции:

"C:\Daten\tmp\DemoProject\simple\build\ALL_BUILD.vcxproj" (Standardziel) (1) ->
"C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj" (Standardziel) (4) ->
(Link Ziel) ->
  MainLib.obj : error LNK2019: unresolved external symbol _doFeature referenced in function _MainLib [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]
  C:\Daten\tmp\DemoProject\simple\build\Debug\MainLib.dll : fatal error LNK1120: 1 unresolved externals [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]

    0 Warnung(en)
    2 Fehler

Возможно ли это даже с Windows?Что мне нужно сделать, чтобы заставить его работать, и как я могу это проверить, кроме как не связывать FeatureLib с MainLibDemo.Любые идеи приветствуются.

С уважением, Флориан

1 Ответ

0 голосов
/ 19 октября 2018

То, как вы это делаете в Linux, не будет работать в Windows, потому что динамическое связывание здесь работает иначе.Вот одна стратегия, которая могла бы работать.

В MainLib.dll коде, вместо прямого вызова doFeature, вам нужно определить глобальную переменную-указатель соответствующего типа указателя на функцию и использовать ее для вызова функции.Это позволит построить MainLib.dll без ошибок.

Теперь вам нужно установить эту переменную указателя.Одним из способов может быть:

  • Добавить экспортированную функцию в MainLib.dll, которая берет указатели на все функции, которые необходимы DLL из исполняемого файла.

  • В коде FeatureLib.lib добавьте функцию инициализации, которую приложение должно будет вызывать перед использованием вашей DLL, которая будет передавать указатели на его одноранговые узлы в DLL.

Это в основном то, как большинство программс помощью плагинов, чтобы предоставить плагинам доступ к их объектам.

Другой способ будет (Предупреждение! Я не проверял это конкретное решение):

  • Объявить функциив FeatureLib.lib как экспортировано с __declspec(dllexport).Таким образом, они будут экспортированы из исполняемого файла.

  • В MainLib.dll перед первым использованием указателей используйте GetModuleHandle и GetProcAddress для получения указателей.Лучше всего это сделать в некоторой функции инициализации библиотеки.В противном случае вам нужно позаботиться о том, чтобы избежать условий гонки.

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

...