Разрешить импорт функций из dll что это значит

Обновлено: 07.07.2024

Я хотел бы простой пример экспорта функции из библиотеки DLL windows C++.

Я хотел бы видеть заголовок, файл cpp и файл Def (если необходимо).

Я бы хотел, чтобы экспортировать имя без отделки. Я хотел бы использовать самое стандартное соглашение о вызовах (__stdcall?). Я бы хотел использовать _ _ declspec (dllexport) и не нужно использовать DEF-файл.

Я пытаясь избежать компоновщик добавил подчеркивания и / или цифры (количество байтов?) к названию.

Я в порядке, не поддерживая dllimport и dllexport, используя один и тот же заголовок. Мне не нужна информация об экспорте методов класса C++, только глобальные функции c-стиля.

обновление

Я в порядке с ответом, что я должен использовать DEF-файл.

Если вам нужна обычная экспорта, использовать проект C не c++. Библиотеки DLL C++ полагаются на искажение имен для всех измов C++(пространства имен и т. д. ). Вы можете скомпилировать свой код как C, перейдя в настройки вашего проекта в разделе C/C++->Advanced, есть опция "Compile As", которая соответствует переключателям компилятора /TP и /TC.

экспорт / импорт библиотек DLL в VC++

то, что вы действительно хотите сделать, это определить условный макрос в заголовке, которые будут включены в исходные файлы в вашем проекте DLL:

затем в функции, которую вы хотите экспортировать, вы используете LIBRARY_API :

в вашей библиотеке построить проект создать define LIBRARY_EXPORTS это приведет к тому, что ваши функции будут экспортированы для вашей сборки DLL.

С LIBRARY_EXPORTS не будет определен в проекте, использующем DLL, когда этот проект включает в себя файл заголовка вашей библиотеки все функции будут импортированы вместо этого.

если ваш библиотека должна быть кросс-платформенной вы можете определить LIBRARY_API как ничто, когда не на Windows:

при использовании атрибутом dllexport/атрибута DllImport вам не нужно использовать Def-файлов, если вы используете Def файлы, вам не нужно использовать с атрибутом dllexport/атрибута DllImport. Два метода выполняют одну и ту же задачу по-разному, я считаю, что dllexport/dllimport является рекомендуемым методом из двух.

экспорт несвязанных функций из библиотеки DLL C++ для LoadLibrary / PInvoke

если вы нужно это использовать LoadLibrary и GetProcAddress, или, может быть, делать PInvoke из .NET вы можете использовать extern "C" встроенный в ваш dllexport. И поскольку мы используем GetProcAddress вместо dllimport, нам не нужно выполнять танец ifdef сверху, просто простой dllexport:

Код:

и вот как выглядит экспорт с помощью Dumpbin / exports:

так этот код отлично работает:

Для C++ :

я просто столкнулся с той же проблемой, и я думаю, что стоит упомянуть, что проблема возникает, когда один использует оба __stdcall (или WINAPI )и extern "C" :

как известно extern "C" удаляет украшение так, что вместо:

вы получаете имя символа без украшений:

на _stdcall (=макрос WINAPI, который изменяет соглашение о вызове) также украшает имена так что если мы используем оба мы получаем:

и в пользу extern "C" теряется, потому что символ украшен (с _ @байт)

обратите внимание, что это только происходит для архитектуры x86, потому что элемент __stdcall соглашение игнорируется на x64 ( msdn:на архитектурах x64, по соглашению, аргументы передаются в регистры, когда это возможно, и последующие аргументы передаются на стек.).

это особенно сложно, если вы ориентируетесь на платформы x86 и x64.

два решения

используйте файл определения. Но это заставляет Вас поддерживать состояние файла Def.

самый простой способ : определить макрос (см. msdn):

и затем включите следующую прагму в тело функции:

это позволит экспортировать функцию без изменений для целей x86 и x64 при сохранении __stdcall Соглашение для x86. Элемент __declspec(dllexport) не требуются в этом случае.


Если вы торгуете на бирже через торговую платформу то, наверное, не раз сталкивались с фразой разрешить импорт DLL при настройке советника или индикатора.

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

Так, что же такое импорт DLL для чего этот импорт нужен и стоит ли разрешать использовать данную настройку.

Торгуй по крупному только с ведущим брокером

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

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

Ну, во-первых, библиотеки постоянно обновляются, а скриптах далеко не всегда предусмотрено автоматическое обновление.

А во-вторых, библиотека может содержать довольно большой объем данных которые в десятки раз увеличат вес советника или индикатора:


Поэтому если не разрешать импорт DLL многие скрипты попросту не запустятся, а если и запустятся, то будут работать не совсем эффективно, используя устаревшие данные.

Чем опасен импорт DLL

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

Правда, если вы используете встроенные в metatrader индикаторы вероятность подхватить вредоносный код после включения импорта DLL практически равна нулю.

Более высока вероятность при установке индикаторов или советников от не проверенных разработчиков, то опасность значительно возрастает.

Но все же практически отсутствует информация о попадание на компьютер через импорт DLL используемый в торговой платформе.

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

Предупреждение о рисках.

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

Создание заметок к вызовам с помощью __declspec(dllimport) может ускорить их работу. __declspec(dllimport) всегда требуется для доступа к экспортированным данным библиотеки DLL.

Импорт функции из библиотеки DLL

В следующем примере кода показано, как использовать __declspec(dllimport) для импорта вызовов функций из библиотеки DLL в приложение. Предположим, что func1 — это функция, которая находится в библиотеке DLL, отделенной от исполняемого файла, который содержит функцию main.

Без __declspec(dllimport) с учетом этого кода:

компилятор формирует код, аналогичный следующему:

и компоновщик преобразует вызов в нечто вроде следующего:

Если func1 существует в другой библиотеке DLL, компоновщик не сможет разрешить этот адрес напрямую, поскольку он не имеет возможности узнать, какой адрес присвоен func1 . В 32-разрядных и 64-разрядных средах компоновщик создает преобразователь по известному адресу. В 32-разрядной среде преобразователь выглядит следующим образом:

Здесь __imp_func1 — это адрес для слота func1 в таблице адресов импорта исполняемого файла. Все эти адреса известны компоновщику. Загрузчику необходимо обновить таблицу адресов импорта исполняемого файла во время загрузки, чтобы все работало правильно.

Вот почему использование __declspec(dllimport) предпочтительнее: компоновщик не создает преобразователь, если он не требуется. Преобразователи усложняют код (в системах RISC это может быть несколько инструкций), что может привести к снижению производительности кэша. Если сообщить компилятору, что функция находится в библиотеке DLL, она может создать косвенный вызов.

Теперь этот код:

создает следующую инструкцию:

Нет ни преобразователя, ни инструкции jmp , поэтому код будет меньше и быстрее. Также можно получить тот же результат без __declspec(dllimport) с помощью оптимизации всей программы. Дополнительные сведения см. в разделе /GL (оптимизация всей программы).

Для вызовов функций в библиотеке DLL не требуется использовать косвенный вызов. Компоновщик уже знает адрес функции. Загрузка и сохранение адреса функции перед прямым вызовом занимает дополнительное время и место. Прямой вызов всегда выполняется быстрее и проще. Вам необходимо использовать __declspec(dllimport) только при вызове функций DLL извне самой библиотеки DLL. Не используйте __declspec(dllimport) в функциях внутри библиотеки DLL при построении этой библиотеки DLL.

Чтобы использовать функции dll, надо (при динамическом варианте)

descr = LoadLibrary("libAdr");
funcPointer= (functype)GetProcAddress(descr,"funcName")

Но для этого всего надо совершенно точно знать, какие функции из библиотеки импортируешь. Их тип.

А нельзя ли использовать функции, о существовании которых не знал до этого?
То есть использовать совершенно левую библиотеку.

Ситуация такая.
Есть мой exe файл.
При его запуске выскакивает консоль, в которой можно какие-то команды писать и параметры для команд.
Есть команды, которые я сам писал и они жестко вбиты в код программы.
"Если написано x, делай y"

Надо сделать так, чтобы работать с dll, которые сам же динамически и подгружаешь. Это не проблема (LoadLibrary). У меня это выглядит - в консоли пишешь :
ld< xxx
и загружается нужная библиотека xxx.

Пользователь знает, что в dll, которую он только что загрузил, есть функция
typeFunc add (typex x,typey y,typez z)
Он в консоли пишет :
add xx,yy,zz

Я считываю это, анализирую и должен написать по идее :
p = (typeFunc(*)(typex)(typey)(typez))getprocaddress(descr,"add")
И вызывать функцию через указатель p:
(*p)(xx,yy,zz);
Но вот тут проблема в том, что программа не знает заранее, что за тип будет у функции.
Если имя функции я узнаю от пользователя, то с типом не получается.
Неужели единственный вариант - это заставить пользователя и тип указывать?
(и возвращаемого значения, и параметров)

Есть способ лучше?
Итак, моя задача( идеал:) ) - не ограничивать набор возможных функций.

Ведь при подключении lib файла программа получает ссылки на функции.
Можно ли это как-нибудь использовать?

То есть, скажем, сделать так, чтобы при подключении новой dll с новой функциональностью надо было перекомпилировать программу с указанием для линкера новой lib.
То есть фиг с ним. Пусть нужна будет перекомпиляция.
Главное, чтобы не надо было менять кода программы.
Есть какое-то решение таким способом? Или обязательно в стек лезть придется?

Posted via ActualForum NNTP Server 1.2

По поводу первого варианта.
Вот объявил я такой указатель.
Но при компиляции то я не знаю, сколько со сколькими параметрами буду ее вызывать.
То есть будет
if(paramNumber == 1)
p(x1);
else if(paramNumber == 2)
P(x1,x2);

В принципе не так плохо. Тем более, параметров будет ну точно не больше 10.

Но как быть с типами?
Подбирать? Идея есть в принципе. Попробую сейчас.

Posted via ActualForum NNTP Server 1.2

Согласен.
Но пользователь при вводе в консоль задает параметры какие-то. Я собираюсь их просто посчитать.
А если он ошибся.
Не повезло ему:)
Вот с типами будет напряжнее. Хотя и решаемо. Надеюсь:)

Posted via ActualForum NNTP Server 1.2

А для чего это ему может быть надо?
Защита от дураков еще понятно, но от людей с мазохистским уклоном.

там найдёте ответы на Ваши вопросы. Останеться только специфицировать интерфейс "описания". И вообще тогда пользователю не нуна будет указывать всю байду, типа наименований функций, кол-во параметров и их типизация.
Интерфейс - есть СОГЛАШЕНИЕ между Вашей программкой и внешними ДэЛеЛе.

Для импорта функций во время выполнения mql4-программы используется так называемое позднее связывание. Это значит, что пока не вызвана импортируемая функция, соответствующий модуль (ex4 или dll) не загружается. Библиотеки MQL4 и DLL выполняются в потоке вызывающего модуля.

Не рекомендуется использовать полностью квалифицированное имя загружаемого модуля вида Drive:\Directory\FileName.Ext. Библиотеки MQL4 загружаются из папки terminal_dir\experts\libraries. Если библиотека не была найдена, то производится попытка загрузить библиотеку из папки terminal_dir\experts.

Системные библиотеки (DLL-Dynamic link libraries) загружаются по правилам операционной системы. Если файл библиотеки уже загружен (к примеру, другим советником и даже из другого клиентского терминала, запущенного параллельно), то обращение программы выполняется к уже загруженной библиотеке, иначе поиск идет в следующем порядке:
1. Каталог terminal_dir\experts\libraries.
2. Каталог , из которого запущен клиентский терминал terminal_dir.
3. Текущий каталог.
4. Системный каталог windows_dir\SYSTEM32.
5. Каталог , в который установлена операционная система windows_dir.
6. Каталоги , перечисленные в системной переменной окружения PATH.

В случае, если одна библиотека DLL использует в своей работе другую DLL, то если отсутствует вторая DLL, то первая не сможет загрузиться.

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

Пример: модуль myfuncs.ex4 вызывает функции из библиотеки mylib1.ex4 и mylib2.ex4. В свою очередь, DLL mylib1.ex4 вызывает функции из библиотеки mylib2.ex4. Таким образом будет загружена одна копия библиотеки mylib1.ex4 и две копии библиотеки mylib2.ex4, несмотря на то, что все вызовы исходят из модуля myfuncs.ex4.

Функции, импортируемые из библиотеки в mql-программу, должны обеспечивать соглашение о связях, принятое для функций Windows API. Для обеспечения такого соглашения в исходном тексте программ, написанных на языках C или C++ используется ключевое слово __stdcall, которое является специфическим для компиляторов от фирмы Microsoft(r). Обсуждаемое соглашение о связях характеризуется следующим:

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

Читайте также: