Преобразование статической библиотеки ссылок в динамическую dll
У меня есть .lib файл с его заголовком (.h). Этот файл имеет несколько функций, которые необходимо использовать в приложении С#.
После googling я обнаружил, что мне нужно создать динамическую DLL из этой статической библиотеки и вызвать эту динамическую DLL из кода С# с помощью interop.
- Я создал проект win32 и DLL выбранного типа.
-
Включен заголовочный файл и добавлен .lib для дополнительных зависимостей.
Я могу видеть функции, определенные в статической библиотеке (когда я нажимаю Ctrl + пробел).
Как новичок, я не знаю, как я могу экспортировать функцию, которая находится в .lib со следующей подписью:
void testfun( char* inp_buff, unsigned short* inp_len, char* buffer_decomp,unsigned *output_len,unsigned short *errorCode)
Я хочу такую же подпись в моей динамической DLL с другим именем.
Что писать в файле заголовка и файле .cpp?
Ответы
Ответ 1
Если вы можете перекомпилировать свою lib, просто добавьте __declspec(dllexport)
в подписи всех функций, которые вы хотите экспортировать.
void __declspec(dllexport) testfun( char* inp_buff, unsigned short* inp_len, char* buffer_decomp,unsigned *output_len,unsigned short *errorCode)
Если вы не можете этого сделать, вы можете экспортировать их, записав вместо этого файл .def. Используя файлы def, вы можете даже изменить имя функции по мере ее экспорта.
http://msdn.microsoft.com/en-us/library/28d6s79h.aspx
---- содержимое mylib.def ----
LIBRARY
EXPORTS
testfun
newname=testfun2
Затем, когда вы связываете DLL, включите mylib.def
link /dll /machine:x86 /def:mylib.def mylib.lib
Edit2:
Обратите внимание, что pinvoke предполагает, что функции, которые вы импортируете, будут иметь _stdcall вызов, если вы не скажете иначе. Таким образом, вам может понадобиться сделать это также в коде С#.
[DllImport("mylib.dll", CallingConvention=CallingConvention.Cdecl)]
Или вы можете изменить свой код на С++ на __stdcall
void __declspec(dllexport) __stdcall testfun( char* inp_buff, ...
Ответ 2
Создайте новый проект Dll с помощью мастера приложений Visual Studio и установите флажок "Экспорт символов" на одном из шагов мастера. Он создает образец Dll, который экспортирует класс, функцию и переменную. Вы можете узнать из этого примера, как это сделать.
Как правило, каждая экспортированная функция объявляется как __declspec (dllexport). В клиентском проекте он объявлен как __declspec (dllimport). Код Dll использует константу, которая осквернена как __declspec (dllexport) внутри проекта Dll, и __declspec (dllimport) в любом другом месте.
Ответ 3
Это то, что вы можете сделать
-
Добавьте к вам следующий код .H. переименуйте "MYPROJECT" в название вашего проекта
#ifdef MYPROJECT_EXPORTS
#define MYPROJECT_API __declspec(dllexport)
#else
#define MYPROJECT_API _declspec(dllimport)
#endif
-
Перейдите в Properties- > С++ → Preprocessor и добавьте defenition - MYPROJECT_EXPORTS
-
Добавьте MYPROJECT_API ко всем функциям, которые вы хотите открыть dll, например:
MYPROJECT_API void Test();
-
Перейти к свойствам проекта Общие → Тип конфигурации изменить его на Dynamic Dll
Вы закончили
Ответ 4
Целевая dll, я пишу, является оберткой для популярной библиотеки lzo.
Я создал проект под названием LZO.
Вот как это выглядит в моем реальном приложении.
LZO.h
#ifdef LZO_EXPORTS
#define LZO_API __declspec(dllexport)
#else
#define LZO_API __declspec(dllimport)
#endif
extern "C" LZO_API void Decompress(char* inp_buff,
unsigned short* inp_len, char* buffer_decomp,unsigned *output_len);
LZO.cpp
#include "stdafx.h"
#include "LZO.h"
#include "lzo1z.h"
#include "lzoconf.h"
#include "lz_decomp.c"
LZO_API void Decompress(char* inp_buff, unsigned short* inp_len, char*
buffer_decomp,unsigned *output_len)
{
//Calling from static library
lzo_decomp (inp_buff,inp_len,buffer_decomp,output_len,NULL);
}
И завершите мой код С#
//P/Invoke declaration
[DllImport("LZO.dll")]
private static extern void Decompress(
byte[] inp_buff,
int inp_len,
byte[] buffer_decomp,
ref int output_len
);
//And calling it as below
Decompress(src, src.Length, dst, ref outlen);
// src is byte []
// dst is also a byte []
// oulen is int
где am я wrog???
Ответ 5
можно создать две версии LIB,
кулак - это динамический lib, (исходный файл + заголовок + динамический lib) → для доступа к DLL
или static lib = (dynamic lib + DLL) → (исходный файл + заголовок) → для доступа к DLL.
если у вас есть Dynamic Lib > нет возможности создать DLL (вы ничего не можете получить из ничего), динамическая lib - это просто интерфейс,
но если у вас есть Static Lib, тогда нет необходимости в DLL для доступа к его функциям.
Ответ 6
Взгляните на мой ответ на этот вопрос для возможного решения. Почти положительное это будет работать для вас...
Вкратце: включите параметр "Использовать вкладки зависимостей библиотеки" в настройках компоновщика. Если установлено значение "true", это заставит связывать ВСЕ символы и код, объявленные в каждой LIB, указанной в качестве входных данных для проекта.
Ответ 7
Проблема здесь не в том, как декорирован код, это дополнительный шаг создания статической библиотеки, содержащей все точки входа, и попытки построить DLL из этого.
Если вы идете с подходом __delcspec и сначала создаете статическую библиотеку, а затем попытайтесь установить ссылку на него при построении DLL, вам придется решить проблему с отсечкой кода.
Когда вы связываете, obj srcs используются для поиска всех украшенных экспонатов и зависимостей, разрешаются все остальное. Если у вас нет DLL src, поэтому никаких файлов obj (кроме, возможно, dll main), весь код в lib, который вы хотите экспортировать, будет удален (независимо от атрибутов).
Итак, вам либо нужно:
- Скажите компоновщику, чтобы он не удалял неиспользуемый код, что, вероятно, даст вам много чего вам не нужно.
- Используйте файл def, чтобы вручную экспортировать экспорт.
- Свяжите dll с файлами obj, используемыми для создания lib, а не напрямую для ссылки на lib.
- Или, может быть, создать фиктивный код, который ссылается на функции, которые вы хотите экспортировать, из того, что вы экспортируете.